Skip to content

Commit b2fb239

Browse files
Required translation updates for Spanish (#1028)
Required translation updates for Spanish in different issues: - #932 - #940 - #957 - #963 - #966 - #994 --------- Co-authored-by: TheHandyOwl <[email protected]>
1 parent f99ed9b commit b2fb239

File tree

7 files changed

+168
-27
lines changed

7 files changed

+168
-27
lines changed

docs/basics/validation.es.md

+60
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,63 @@ Los validadores también pueden combinarse mediante operadores para construir va
227227
|`!`|prefijo|Invierte un validador, requiriendo lo opuesto.|
228228
|`&&`|infijo|Combina dos validadores, requiere ambos.|
229229
|`||`|infijo|Combina dos validadores, requiere al menos uno.|
230+
231+
## Validadores Personalizados
232+
233+
Crear un validador personalizado para códigos postales te permite extender la funcionalidad del marco de validación. En esta sección, te guiaremos a través de los pasos para crear un validador personalizado que valide códigos postales.
234+
235+
Primero, crea un nuevo tipo para representar los resultados de la validación de `ZipCode`. Esta estructura será responsable de informar si una cadena dada es un código postal válido.
236+
237+
```swift
238+
extension ValidatorResults {
239+
/// Representa el resultado de un validador que verifica si una cadena es un código postal válido.
240+
public struct ZipCode {
241+
/// Indica si la entrada es un código postal válido.
242+
public let isValidZipCode: Bool
243+
}
244+
}
245+
```
246+
247+
A continuación, haz que el nuevo tipo cumpla con `ValidatorResult`, que define el comportamiento esperado de un validador personalizado.
248+
249+
```swift
250+
extension ValidatorResults.ZipCode: ValidatorResult {
251+
public var isFailure: Bool {
252+
!self.isValidZipCode
253+
}
254+
255+
public var successDescription: String? {
256+
"is a valid zip code"
257+
}
258+
259+
public var failureDescription: String? {
260+
"is not a valid zip code"
261+
}
262+
}
263+
```
264+
265+
Finalmente, implementa la lógica de validación para los códigos postales. Usa una expresión regular para verificar si la cadena de entrada coincide con el formato de un código postal de EE.UU.
266+
267+
```swift
268+
private let zipCodeRegex: String = "^\\d{5}(?:[-\\s]\\d{4})?$"
269+
270+
extension Validator where T == String {
271+
/// Valida si una cadena es un código postal válido.
272+
public static var zipCode: Validator<T> {
273+
.init { input in
274+
guard let range = input.range(of: zipCodeRegex, options: [.regularExpression]),
275+
range.lowerBound == input.startIndex && range.upperBound == input.endIndex
276+
else {
277+
return ValidatorResults.ZipCode(isValidZipCode: false)
278+
}
279+
return ValidatorResults.ZipCode(isValidZipCode: true)
280+
}
281+
}
282+
}
283+
```
284+
285+
Ahora que has definido el validador personalizado `zipCode`, puedes usarlo para validar códigos postales en tu aplicación. Simplemente agrega la siguiente línea a tu código de validación:
286+
287+
```swift
288+
validations.add("zipCode", as: String.self, is: .zipCode)
289+
```

docs/fluent/model.es.md

+7-5
Original file line numberDiff line numberDiff line change
@@ -359,12 +359,14 @@ app.get("planets") { req async throws in
359359

360360
Al serializar desde/hacia `Codable`, las propiedades del modelo usarán sus nombres de variable en lugar de las claves. Las relaciones serán serializadas como estructuras anidadas y cualquier carga previa (eager loading) de datos será incluida.
361361

362+
!!! info "Información"
363+
Recomendamos que para casi todos los casos utilices un DTO en lugar de un modelo para tus respuestas de API y los cuerpos de tus solicitudes. Consulta [Objeto de transferencia de datos](#data-transfer-object) para obtener más información.
364+
362365
### Data Transfer Object
363366

364-
La conformidad por defecto del modelo a `Codable` puede facilitar el prototipado y usos simples. Sin embargo, no se ajusta a todos los casos de uso. Para ciertas situaciones necesitarás usar un data transfer object (DTO).
367+
La conformidad por defecto del modelo a `Codable` puede facilitar el prototipado y usos simples. Sin embargo, expone la información subyacente de la base de datos a la API. Esto generalmente no es deseable desde un punto de vista de seguridad —devolver campos sensibles como el hash de la contraseña de un usuario es una mala idea— y desde una perspectiva de usabilidad. Hace difícil cambiar el esquema de la base de datos sin romper la API, aceptar o devolver datos en un formato diferente, o agregar o eliminar campos de la API.
365368

366-
!!! tip "Consejo"
367-
Un DTO es un tipo `Codable` aparte que representa la estructura de datos que quieres codificar/descodificar.
369+
En la mayoría de los casos, deberías usar un DTO o data transfer object (objeto de transferencia de datos) en lugar de un modelo (también conocido como domain transfer object). Un DTO es un tipo `Codable` separado que representa la estructura de datos que deseas codificar o decodificar. Esto desacopla tu API del esquema de la base de datos y te permite realizar cambios en tus modelos sin romper la API pública de tu aplicación, tener diferentes versiones y hacer que tu API sea más agradable de usar para tus clientes.
368370

369371
Toma como base el siguiente modelo de `User` para los ejemplos a continuación.
370372

@@ -434,9 +436,9 @@ app.get("users") { req async throws -> [GetUser] in
434436
}
435437
```
436438

437-
Aunque la estructura del DTO sea idéntica a la del modelo conformado con `Codable`, tenerlo como tipo aparte puede ayudar a mantener los proyectos grandes ordenados. Si necesitaras hacer un cambio en las propiedades de tu modelo, no tienes que preocuparte de si rompes la API pública de tu app. Puedes considerar agrupar tus DTO en un package aparte que puedas compartir con los consumidores de tu API.
439+
Otro caso de uso común es al trabajar con relaciones, como relaciones de padre o de hijos. Consulta [la documentación de Parent](relations.es.md#codificación-y-decodificación-de-relaciones-parent) para ver un ejemplo de cómo usar un DTO para facilitar la decodificación de un modelo con una relación `@Parent`.
438440

439-
Por estas razones, recomendamos encarecidamente usar DTO siempre que sea posible, especialmente en proyectos grandes.
441+
Incluso si la estructura del DTO es idéntica a la conformidad `Codable` del modelo, tenerlo como un tipo separado puede ayudar a mantener organizados los proyectos grandes. Si alguna vez necesitas realizar un cambio en las propiedades de tus modelos, no tendrás que preocuparte por romper la API pública de tu aplicación. También puedes considerar colocar tus DTOs en un paquete separado que pueda ser compartido con los consumidores de tu API y agregar conformidad a `Content` en tu aplicación Vapor.
440442

441443
## Alias
442444

docs/fluent/relations.es.md

+45-4
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,39 @@ La definición del campo es similar a la de `@Parent`, excepto la constraint `.r
6161
.field("star_id", .uuid, .references("star", "id"))
6262
```
6363

64+
### Codificación y Decodificación de Relaciones Parent
65+
66+
Algo a tener en cuenta al trabajar con relaciones `@Parent` es la forma en que se envían y reciben. Por ejemplo, en JSON, una relación `@Parent` para un modelo `Planet` podría verse así:
67+
68+
```json
69+
{
70+
"id": "A616B398-A963-4EC7-9D1D-B1AA8A6F1107",
71+
"star": {
72+
"id": "A1B2C3D4-1234-5678-90AB-CDEF12345678"
73+
}
74+
}
75+
```
76+
77+
Nota cómo la propiedad `star` es un objeto en lugar del ID que podrías esperar. Al enviar el modelo como un cuerpo HTTP, debe coincidir con esta estructura para que la decodificación funcione. Por esta razón, recomendamos encarecidamente usar un DTO para representar el modelo al enviarlo por la red. Por ejemplo:
78+
79+
```swift
80+
struct PlanetDTO: Content {
81+
var id: UUID?
82+
var name: String
83+
var star: Star.IDValue
84+
}
85+
```
86+
87+
Luego puedes decodificar el DTO y convertirlo en un modelo:
88+
89+
```swift
90+
let planetData = try req.content.decode(PlanetDTO.self)
91+
let planet = Planet(id: planetData.id, name: planetData.name, starID: planetData.star)
92+
try await planet.create(on: req.db)
93+
```
94+
95+
Lo mismo aplica al devolver el modelo a los clientes. Tus clientes deben poder manejar la estructura anidada o necesitas convertir el modelo en un DTO antes de devolverlo. Para más información sobre los DTOs, consulta la [documentación del modelo](model.es.md#data-transfer-object).
96+
6497
## Optional Child
6598

6699
La propiedad `@OptionalChild` crea una relación uno a uno entre dos modelos. No guarda ningún valor en el modelo raíz.
@@ -284,7 +317,7 @@ Ver [query](query.md) para más información.
284317

285318
## Eager Loading
286319

287-
El constructor de consultas (query builder) de Fluent te permite precargar las relaciones de un modelo cuando es recuperado de la base de datos. Esto se conoce como "eager loading" y te permite acceder a las relaciones de manera sincrónica sin la necesidad de llamar previamente a [`load`](#lazy-eager-loading) o [`get`](#get) .
320+
El constructor de consultas (query builder) de Fluent te permite precargar las relaciones de un modelo cuando es recuperado de la base de datos. Esto se conoce como "eager loading" y te permite acceder a las relaciones de manera sincrónica sin la necesidad de llamar a [`get`](#get) primero.
288321

289322
Para hacer un "eager load" de una relación, pasa un key path a la relación con el método `with` en el constructor de consultas.
290323

@@ -311,6 +344,7 @@ for planet in planets {
311344
En el ejemplo anterior, se le ha pasado un key path a la relación [`@Parent`](#parent) llamada `star` con `with`. Esto provoca que el constructor de consultas haga una consulta adicional después de cargar todos los planetas para recuperar todas las estrellas conectadas a éstos. Las estrellas son accesibles de manera sincrónica mediante la propiedad `@Parent`.
312345

313346
Cada relación precargada (eager loaded) necesita una única consulta adicional, sin importar cuántos modelos se hayan devuelto. La precarga (eager loading) sólo es posible con los métodos de constructor de consultas `all` y `first`.
347+
314348
### Nested Eager Load
315349

316350
El método de constructor de consultas `with` te permite precargar relaciones en el modelo que está siendo consultado. Sin embargo, también puedes precargar relaciones en los modelos conectados.
@@ -330,16 +364,23 @@ El método `with` acepta un closure opcional como segundo parámetro. Este closu
330364

331365
## Lazy Eager Loading
332366

333-
En caso de que ya hayas recuperado el modelo del parent y quieres cargar una de sus relaciones, puedes usar el método `load(on:)` para hacerlo. Esto recuperará el modelo conectado de la base de datos y permitirá acceder a él como una propiedad local.
367+
En caso de que ya hayas recuperado el modelo del parent y quieres cargar una de sus relaciones, puedes usar el método `get(reload:on:)` para hacerlo. Esto recuperará el modelo conectado de la base de datos (o de la caché, si está disponible) y permitirá acceder a él como una propiedad local.
334368

335369
```swift
336-
planet.$star.load(on: database).map {
370+
planet.$star.get(on: database).map {
337371
print(planet.star.name)
338372
}
339373

340374
// O
341375

342-
try await planet.$star.load(on: database)
376+
try await planet.$star.get(on: database)
377+
print(planet.star.name)
378+
```
379+
380+
En caso de que quieras asegurarte de que los datos que recibes no se obtienen desde la caché, utiliza el parámetro `reload:`.
381+
382+
```swift
383+
try await planet.$star.get(reload: true, on: database)
343384
print(planet.star.name)
344385
```
345386

docs/fluent/schema.es.md

+22-3
Original file line numberDiff line numberDiff line change
@@ -380,15 +380,34 @@ Podemos hacer los ajustes necesarios del esquema de la base de datos con la sigu
380380
```swift
381381
struct UserNameMigration: AsyncMigration {
382382
func prepare(on database: Database) async throws {
383+
try await database.schema("users")
384+
.field("first_name", .string, .required)
385+
.field("last_name", .string, .required)
386+
.update()
387+
388+
// Actualmente no es posible expresar esta actualización sin usar SQL personalizado.
389+
// Esto tampoco intenta dividir el nombre en nombre y apellido,
390+
// ya que eso requiere sintaxis específica de la base de datos.
391+
try await User.query(on: database)
392+
.set(["first_name": .sql(embed: "name"))
393+
.run()
394+
383395
try await database.schema("users")
384396
.deleteField("name")
385-
.field("first_name", .string)
386-
.field("last_name", .string)
387397
.update()
388398
}
389399

390400
func revert(on database: Database) async throws {
391-
try await database.schema("users").delete()
401+
try await database.schema("users")
402+
.field("name", .string, .required)
403+
.update()
404+
try await User.query(on: database)
405+
.set(["name": .sql(embed: "concat(first_name, ' ', last_name)"))
406+
.run()
407+
try await database.schema("users")
408+
.deleteField("first_name")
409+
.deleteField("last_name")
410+
.update()
392411
}
393412
}
394413
```

docs/install/linux.es.md

+26-13
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,38 @@
11
# Instalación en Linux
22

3-
Para usar Vapor, necesitas Swift 5.9 o superior. Se puede instalar usando las opciones disponibles en [Swift.org](https://swift.org/download/).
3+
Para usar Vapor, necesitas Swift 5.9 o superior. Esto se puede instalar utilizando la herramienta CLI [Swiftly](https://swiftlang.github.io/swiftly/) proporcionada por el Swift Server Workgroup (recomendado), o las toolchains disponibles en [Swift.org](https://swift.org/download/).
44

55
## Distribuciones y Versiones Soportadas
66

7-
Vapor admite las mismas versiones de distribución de Linux que adminte Swift 5.9 o versiones más recientes.
8-
9-
!!! nota
10-
Las versiones soportadas que se enumeran a continuación pueden quedar obsoletas en cualquier momento. Puedes comprobar qué sistemas operativos son oficialmente compatibles en la página [Swift Releases](https://swift.org/download/#releases).
11-
12-
|Distribución|Versión|Versión de Swift|
13-
|-|-|-|
14-
|Ubuntu|20.04|>= 5.9|
15-
|Fedora|>= 30|>= 5.9|
16-
|CentOS|8|>= 5.9|
17-
|Amazon Linux|2|>= 5.9|
7+
Vapor es compatible con las mismas versiones de distribuciones de Linux que soportan Swift 5.9 o versiones posteriores. Por favor, consulta la [página oficial de soporte](https://www.swift.org/platform-support/) para obtener información actualizada sobre los sistemas operativos oficialmente compatibles.
188

199
Las distribuciones de Linux que no son oficialmente compatibles también pueden ejecutar Swift al compilar el código fuente, pero Vapor no puede garantizar estabilidad. Puedes aprender más sobre cómo compilar Swift desde [Swift Repo](https://github.com/apple/swift#getting-started).
2010

2111
## Instalar Swift
2212

13+
### Instalación automatizada usando la herramienta Swiftly CLI (recomendada)
14+
15+
Visita el [sitio web de Swiftly](https://swiftlang.github.io/swiftly/) para obtener instrucciones sobre cómo instalar Swiftly y Swift en Linux. Después de eso, instala Swift con el siguiente comando:
16+
17+
#### Uso básico
18+
19+
```sh
20+
$ swiftly install latest
21+
22+
Fetching the latest stable Swift release...
23+
Installing Swift 5.9.1
24+
Downloaded 488.5 MiB of 488.5 MiB
25+
Extracting toolchain...
26+
Swift 5.9.1 installed successfully!
27+
28+
$ swift --version
29+
30+
Swift version 5.9.1 (swift-5.9.1-RELEASE)
31+
Target: x86_64-unknown-linux-gnu
32+
```
33+
34+
### Instalación manual con la toolchain
35+
2336
Visita la guía [Using Downloads](https://swift.org/download/#using-downloads) de Swift.org para ver las instrucciones de cómo instalar Swift en Linux.
2437

2538
### Fedora
@@ -30,7 +43,7 @@ Los usuarios de Fedora pueden simplemente utilizar el siguiente comando para ins
3043
sudo dnf install swift-lang
3144
```
3245

33-
Si utilizas Fedora 30, deberás agregar EPEL 8 para obtener Swift 5.9 o versiones más nuevas.
46+
Si utilizas Fedora 35, deberás agregar EPEL 8 para obtener Swift 5.9 o versiones más nuevas.
3447

3548
## Docker
3649

docs/leaf/getting-started.es.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Leaf es un potente lenguaje de plantillas con una sintaxis inspirada en Swift. P
77
El primer paso para usar Leaf es agregarlo como una dependencia en tu proyecto en tu archivo de manifiesto del paquete SPM.
88

99
```swift
10-
// swift-tools-version:5.2
10+
// swift-tools-version:5.9
1111
import PackageDescription
1212

1313
let package = Package(
@@ -17,7 +17,7 @@ let package = Package(
1717
],
1818
dependencies: [
1919
/// Cualquier otra dependencia ...
20-
.package(url: "https://github.com/vapor/leaf.git", from: "4.0.0"),
20+
.package(url: "https://github.com/vapor/leaf.git", from: "4.4.0"),
2121
],
2222
targets: [
2323
.target(name: "App", dependencies: [

docs/leaf/overview.es.md

+6
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,12 @@ Puede pasar una cadena de formateado de fecha personalizada como segundo argumen
264264
The date is #date(now, "yyyy-MM-dd")
265265
```
266266

267+
También puedes pasar un ID de zona horaria para el formateador de fechas como tercer argumento. Consulta la documentación de Swift sobre [`DateFormatter.timeZone`](https://developer.apple.com/documentation/foundation/dateformatter/1411406-timezone) y [`TimeZone`](https://developer.apple.com/documentation/foundation/timezone) para más información.
268+
269+
```leaf
270+
The date is #date(now, "yyyy-MM-dd", "America/New_York")
271+
```
272+
267273
#### `#unsafeHTML`
268274

269275
La etiqueta `#unsafeHTML` actúa como una etiqueta variable - p. ej. `#(variable)`. Sin embargo, no escapa ningún HTML que `variable` pueda contener:

0 commit comments

Comments
 (0)