Translation into Spanish of an interesting article by Vic Shóstak, software engineer with over 13 years of practical experience (Go, Python, Kotlin, TypeScript), UX Consultant, and Open Source Supporter.
A free translation by Chema, a Spanish translator who loves to translate apps into Spanish
An original text written by Vic Shóstak, originally published in
https://dev.to/koddr/an-easy-way-to-translate-your-golang-application-5ege
* * *
TUTORIAL SOBRE GOLANG (una serie de 13 partes)
1. La forma más fácil de incrustar archivos estáticos en un archivo binario en una aplicación Golang (sin dependencias externas)
2. Escribamos la configuración para su aplicación web Golang de la manera correcta: YAML...
3. ¿Cómo actualizar la caché de la versión en pkg.go.dev?
4. ¿Cómo implementar Golang en cualquier sistema GNU/Linux, pero sin Docker?
5. Una potente CLI para crear un nuevo proyecto listo para producción con backend, frontend y automatización de implementación
6. ¿Qué hay de nuevo y especial en Create Go App CLI v1.7.0?
7. Trabajando con RabbitMQ en Golang, con ejemplos
8. Asynq: cola de tareas distribuida simple, fiable y eficiente para tu próximo proyecto Go
9. Una manera fácil de traducir una aplicación Golang
10. El proyecto Create Go App ha pasado a v2, aún es más fácil, mejor, más rápido y más fuerte
11. ¿Cómo enviar mensajes de error claros y bonitos desde el backend de Go a su frontend?
12. Optimización de consultas PostgreSQL para Gophers: ¡es mucho más fácil de lo que parece!
13. Herramientas útiles de Golang para que tu código vuelva a ser genial
Hablemos de uno de un tema muy importantes si estás preparando una aplicación Go para una audiencia multilingüe o simplemente necesitas soporte de traducción en diferentes idiomas con las APIs REST.
El tema de la traducción no es tan simple como parece, porque cada idioma tiene sus propios elementos especiales especialmente cuando se usan números. Por ejemplo, en ruso hay 3 variantes diferentes para cantidades de artículos:
one
, 1 articulo;few
, 2 artículos;many
, +3 artículos;🤔 ¡Hay que saber esto a la hora de traducir una aplicación!
No te preocupes, pronto explicaremos cómo conseguirlo!
Para aquellos a quienes les gusta ver el código antes de antes, creé un repositorio en GitHub:
koddr / tutorial-go-i18n
📖 Tutorial: Una manera fácil de traducir tu aplicación Golang
He probado muchos paquetes (incluido el integrado en el núcleo de Go), y de todos nicksnyder/go-i18n ha sido el único que realmente me ha gustado. Crearemos nuestra aplicación de demostración usando este paquete en particular.
👋 ¡Escribe en los comentarios qué paquete de i18n usas y por qué!
Usaremos el framework de Fiber como núcleo de nuestra aplicación, ya que tiene una excelente compatibilidad con plantillas (con una función de recarga suave) y permite leer y escribir código de manera sencilla.
🔥 ¡No dejes de leer los comentarios en el código!
// ./main.go
package main
import (
"log"
"strconv"
"github.com/BurntSushi/toml"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/template/html"
"github.com/nicksnyder/go-i18n/v2/i18n"
"golang.org/x/text/language"
)
func main() {
// Create a new i18n bundle with default language.
bundle := i18n.NewBundle(language.English)
// Register a toml unmarshal function for i18n bundle.
bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
// Load translations from toml files for non-default languages.
bundle.MustLoadMessageFile("./lang/active.es.toml")
bundle.MustLoadMessageFile("./lang/active.ru.toml")
// Create a new engine by passing the template folder
// and template extension.
engine := html.New("./templates", ".html")
// Reload the templates on each render, good for development.
// Optional, default is false.
engine.Reload(true)
// After you created your engine, you can pass it
// to Fiber's Views Engine.
app := fiber.New(fiber.Config{
Views: engine,
})
// Register a new route.
app.Get("/", func(c *fiber.Ctx) error {
lang := c.Query("lang") // parse language from query
accept := c.Get("Accept-Language") // or, parse from Header
// Create a new localizer.
localizer := i18n.NewLocalizer(bundle, lang, accept)
// Set title message.
helloPerson := localizer.MustLocalize(&i18n.LocalizeConfig{
DefaultMessage: &i18n.Message{
ID: "HelloPerson", // set translation ID
Other: "Hello {{.Name}}", // set default translation
},
TemplateData: &fiber.Map{
"Name": "John",
},
})
// Parse and set unread count of emails.
unreadEmailCount, _ := strconv.ParseInt(c.Query("unread"), 10, 64)
// Config for translation of email count.
unreadEmailConfig := &i18n.LocalizeConfig{
DefaultMessage: &i18n.Message{
ID: "MyUnreadEmails",
One: "You have {{.PluralCount}} unread email.",
Other: "You have {{.PluralCount}} unread emails.",
},
PluralCount: unreadEmailCount,
}
// Set localizer for unread emails.
unreadEmails := localizer.MustLocalize(unreadEmailConfig)
// Return data as JSON.
if c.Query("format") == "json" {
return c.JSON(&fiber.Map{
"name": helloPerson,
"unread_emails": unreadEmails,
})
}
// Return rendered template.
return c.Render("index", fiber.Map{
"Title": helloPerson,
"UnreadEmails": unreadEmails,
})
})
// Start server on port 3000.
log.Fatal(app.Listen(":3000"))
}
Normalmente, no me gusta usar bibliotecas CSS prefabricadas, pero para esta demostración, por simplicidad y facilidad, he preferido usar la biblioteca Bootstrap 5 (v5.0.0-beta3
):
<!-- ./templates/index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{{.Title}}</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6"
crossorigin="anonymous"
/>
<style>
* {
font-family: sans-serif;
color: #333333;
}
</style>
</head>
<body>
<div class="col-lg-8 mx-auto p-3 py-md-5">
<h1>{{.Title}}</h1>
<br />
<div class="row g-5">
<div class="col-md-6">
<ul class="icon-list">
<li>{{.UnreadEmails}}</li>
</ul>
</div>
</div>
<footer class="pt-5 my-5 text-muted border-top">
Switch to 🇬🇧 <a href="/">English</a>, 🇪🇸
<a href="/?lang=es">Español</a>, 🇷🇺 <a href="/?lang=ru">Русский</a>.
</footer>
</div>
</body>
</html>
goi18n
:go get -u github.com/nicksnyder/go-i18n/v2/goi18n
i18n.Message
de archivos fuente de Go y pásalos a un archivo de mensaje para traducir (de forma predeterminada, active.en.toml
):goi18n extract
# ./active.en.toml
HelloPerson = "Hello {{.Name}}"
[MyUnreadEmails]
one = "You have {{.PluralCount}} unread email."
other = "You have {{.PluralCount}} unread emails."
translate.es.toml
y translate.ru.toml
).touch translate.es.toml translate.ru.toml
goi18n merge
con estos archivos de mensajes a traducir:# For Español:
goi18n merge active.en.toml translate.es.toml
# For Russian:
goi18n merge active.en.toml translate.ru.toml
# ./translate.ru.toml
[HelloPerson]
hash = "sha1-5b49bfdad81fedaeefb224b0ffc2acc58b09cff5"
other = "Привет, {{.Name}}"
[MyUnreadEmails]
hash = "sha1-6a65d17f53981a3657db1897630e9cb069053ea8"
one = "У вас есть {{.PluralCount}} непрочитанное письмо."
other = "У вас есть {{.PluralCount}} непрочитанных писем."
few = "У вас есть {{.PluralCount}} непрочитанных письма." # <-- new row for "few" count
many = "У вас есть {{.PluralCount}} непрочитанных писем." # <-- new row for "many" count
active.es.toml
y active.ru.toml
colóquelos en la ./lang
carpeta.Finalmente estamos listos para lanzar nuestra aplicación:
go run main.go
# ┌───────────────────────────────────────────────────┐
# │ Fiber v2.7.1 │
# │ http://127.0.0.1:3000 │
# │ (bound on host 0.0.0.0 and port 3000) │
# │ │
# │ Handlers ............. 2 Processes ........... 1 │
# │ Prefork ....... Disabled PID ............. 64479 │
# └───────────────────────────────────────────────────┘
ESTÁ BIEN. Abrir http://localhost:3000/
:
Como puedes ver, por defecto, el sitio web siempre se abrirá en 🇬🇧 inglés , como se especifica en la configuración de la aplicación.
💡 En Golang
int
, los valores no establecidos siempre tendrán0
, nonull
oNone
como en JavaScript o Python. Por eso, si no especificamos el
parámetrounread
en una consulta, la plantilla se establecerá en0
.
A continuación, cambiemos el idioma a 🇪🇸 Español. Haz clic en el enlace en la parte inferior de la página y agrega el parámetro de consulta unread
con algún número entero:
Ve a otro idioma, por ejemplo 🇷🇺 Ruso :
👆 Puedes jugar con el valor de
unread
para ver cómo la forma de la palabra cambia automáticamente después de un número.
Para ver cómo funciona JSON, añade un parámetro format=json
a la consulta: Fiber te mostrará el mismo contenido, pero en formato JSON:
En aplicaciones web reales, puedes crear diferentes variantes de los métodos de la API REST para entregar traducciones a la interfaz. Pero lo más importante a recordar si realizas proyectos internacionales, es que debes pensar antes de nada en las particularidades de cada idioma.
¡Golang ayudará con todo lo demás! 🎉
Si deseas más artículos como este, publica un comentario a continuación y suscríbete. ¡Gracias! 😘
Y, por supuesto, puedes apoyarme donando en LiberaPay. Cada donación ayuda a publicar nuevos artículos y desarrollar proyectos de código abierto sin fines de lucro para la comunidad.