El 12 de octubre terminé de subir la ficha de mi diario Lanternly en 39 idiomas. Si se cuentan los campos, salen 819: nombre, subtítulo y enlace a la política en «Información de la app», seis campos de la versión de iOS, cinco de la versión de macOS y las localizaciones de la suscripción, que son el grupo y tres planes. No tengo un equipo de traductores ni una agencia de ASO.
Esto es cómo lo monté y dónde tropecé. Los límites los comprobé con la documentación de App Store Connect el 13 de octubre de 2026.
Primero decidí en qué no se podía mentir#
La interfaz de Lanternly solo está en inglés y en ruso. Una ficha en sueco o en turco crea la expectativa de que la app también estará en sueco o en turco. La persona la descarga, ve el inglés y deja una estrella o pide que le devuelvan el dinero.
Por eso, en todos los idiomas salvo el inglés y el ruso, la segunda línea de la descripción dice lo mismo:
Die App-Oberfläche ist auf Englisch und Russisch.
Appens gränssnitt är på engelska och ryska.Va justo después del primer párrafo, antes de la lista de funciones. Más abajo en el texto nadie la encontraría.
La segunda decisión tenía que ver con el volumen. 14 idiomas recibieron una descripción completa de 3000 a 4000 caracteres, y otros 25 una corta, de unos 1300: de qué va la app, la línea honesta sobre la interfaz, el bloque de la suscripción y los enlaces legales. 11 idiomas de la India decidí no subirlos. No tengo con qué comprobar la calidad de una traducción al hindi o al tamil, y una mala traducción en la ficha es peor que el original en inglés.
Un archivo en lugar de 819 campos de formulario#
Editar 39 idiomas directamente en el formulario de App Store Connect no funciona: corriges una frase de la suscripción en inglés y tienes que acordarte de en qué otros 38 sitios aparece.
La fuente de verdad pasó a ser un único JSON: idioma → campos. Las descripciones de iOS y macOS se diferencian en un último párrafo (el Mac tiene su propia lista de «dónde más funciona»), así que se guarda el texto común y la sustitución para Mac. Cualquier cambio va primero al archivo, pasa la comprobación y solo después llega a la tienda. Al lado hay un TSV con nombres, subtítulos y palabras clave: es cómodo para revisarlo a ojo y para comprobarlo con un script.
Los límites que mandan#
| Campo | Límite | Dónde se define |
|---|---|---|
| Name | 30 caracteres | Información de la app, común a iOS y macOS |
| Subtitle | 30 caracteres | Ahí mismo |
| Keywords | 100 bytes según la documentación | Versión, cada plataforma tiene el suyo |
| Promotional Text | 170 caracteres | Versión, se cambia sin revisión |
| Description | 4000 caracteres | Versión |
| What's New | 4000 caracteres | Versión |
Sobre las palabras clave, la documentación dice: «You can provide up to 100 bytes of content». Bytes, no caracteres. En UTF-8, el cirílico ocupa dos bytes por letra y el japonés, tres. Mis palabras clave en ruso tienen 93 caracteres, que son 176 bytes, y App Store Connect las aceptó sin rechistar. En la práctica se cuentan caracteres, pero yo no contaría con que eso no cambie.
Los puntos más ajustados no estaban donde esperaba. Nombre y subtítulo, de 30 caracteres cada uno, cupieron en todos los idiomas: las palabras compuestas alemanas son largas, pero hay pocas. Choqué con otras cosas:
- El texto promocional en alemán quedó en 170 de 170 exactos. No cabe ni una coma más.
- El texto promocional en neerlandés hubo que recortarlo: la primera versión no cabía.
- La descripción en francés no cabía en 4000. Me salvó que los enlaces a la política y a los términos aparecían dos veces: en el texto y en el bloque obligatorio del final. Quité la repetición y quedó en 3917.
Un script que comprueba lo que el formulario no ve#
App Store Connect solo comprueba la longitud. Todo lo demás lo acepta sin decir nada, y el error, como mucho, lo notarás por la falta de impresiones. Por eso, antes de cada subida paso un pequeño script por el TSV. Esta es su versión simplificada, la que funciona:
#!/usr/bin/env python3
"""Comprobación de name/subtitle/keywords por idioma: python3 check_fields.py fields.tsv"""
import csv, re, sys
LIMITS = {"name": 30, "subtitle": 30, "keywords": 100}
BANNED = {"app", "free", "apple", "iphone"}
def words(s):
return re.findall(r"[\w’'-]+", s.lower())
bad = 0
for r in csv.DictReader(open(sys.argv[1], encoding="utf-8"), delimiter="\t"):
issues = [f"{f}: {len(r[f])}/{n}" for f, n in LIMITS.items() if len(r[f]) > n]
kw = r["keywords"]
if re.search(r",\s", kw):
issues.append("espacio después de la coma")
kw_words = [w for t in kw.split(",") for w in words(t)]
dup = {w for w in kw_words if kw_words.count(w) > 1}
if dup:
issues.append(f"repetición en keywords: {sorted(dup)}")
title = set(words(r["name"] + " " + r["subtitle"]))
if set(kw_words) & title:
issues.append(f"repetición con name/subtitle: {sorted(set(kw_words) & title)}")
if (set(kw_words) | title) & BANNED:
issues.append(f"palabras sobrantes: {sorted((set(kw_words) | title) & BANNED)}")
bad += bool(issues)
print(("FAIL " if issues else "OK ") + r["locale"], *issues, sep="\n - ")
sys.exit(1 if bad else 0)Recibe un TSV con las columnas locale, name, subtitle y keywords. Qué detecta y por qué:
- Espacio después de la coma. Es simplemente un carácter perdido de cien. Apple separa las palabras clave por comas y el espacio no le hace falta.
- Una palabra repetida dentro de las keywords o con el nombre o el subtítulo. Las palabras del nombre y del subtítulo ya cuentan para la búsqueda; repetirlas en las keywords es gastar el espacio dos veces.
- Palabras que no hacen falta.
appyfreeno aportan nada, y los nombres de apps y empresas ajenas la documentación los prohíbe de forma explícita. Mi lista completa es más larga: también incluye palabras que no uso en el producto en absoluto, por ejemplo etiquetas médicas.
Las longitudes de descripciones y textos promocionales las comprueba un segundo script, y el resultado lo guardo en un archivo junto al JSON. Un mes después, en el siguiente cambio, se ve enseguida qué idioma va sin margen.
Cómo traduje#
Los borradores de las traducciones los hice con un modelo de lenguaje. Ningún hablante nativo los revisó. Ocultarlo no tiene sentido: es justo lo que se puede permitir un desarrollador en solitario. Por eso me puse unas cuantas reglas.
Traducir el sentido, no las frases. El texto promocional en inglés «Free to write as much as you like» en alemán quedó como «Schreib, so viel du willst»: la palabra «gratis» no habría cabido en el límite, y el sentido se mantuvo.
Escribir las palabras clave como la gente las teclea. En ruso se busca «дневник эмоций» (diario de emociones) y «дневник с паролем» (diario con contraseña), así que en las keywords van эмоций y паролем, en genitivo y en instrumental: son formas de caso de «emociones» y «contraseña», no las palabras en su forma de diccionario. Los alemanes buscan con palabras compuestas, y dankbarkeitstagebuch va como una sola palabra entera. En polaco, dziennik suele significar el registro escolar electrónico, así que la palabra principal del nombre es Pamiętnik.
Descripciones cortas para los idiomas que no puedo comprobar. Cuanto más corto el texto, menos sitios hay para una frase rara que no voy a detectar.
Enlaces que también hay que localizar#
Los enlaces también hay que localizarlos. Cada idioma tiene su propia Privacy Policy URL, Support URL y Marketing URL, y al final de cada descripción hay un bloque con los enlaces legales. Los documentos en el sitio web están en cinco idiomas, así que los idiomas españoles van a /es/, el japonés a /ja/, los chinos a /zh-CN/ y el resto a /en/. El soporte está en inglés y en ruso. Sobre el bloque EULA en sí y por qué es obligatorio para una suscripción escribí aparte.
La subida: solo con script#
Teclear 819 campos a mano es perder un día y casi seguro equivocarse en alguno. Yo subí todo con un script desde mi sesión de App Store Connect. Si lo haces con regularidad, el camino correcto es la App Store Connect API oficial: tiene los recursos appInfoLocalizations, appStoreVersionLocalizations, subscriptionGroupLocalizations y subscriptionLocalizations, es decir, todo lo que he enumerado arriba.
Dos cosas con las que me topé por el camino:
- La primera versión de Mac no tiene campo What's New. La versión 1.1 de macOS es la primera de Lanternly, así que el campo directamente no existe y el script tiene que saltárselo.
- El nombre y el subtítulo son comunes a iOS y macOS, pero las palabras clave y la descripción son propias de cada plataforma. Las copio tal cual; solo cambia el último párrafo de la descripción.
Lo que queda por hacer#
Las capturas en todos los idiomas nuevos siguen en inglés: la interfaz es en inglés o en ruso de todos modos, así que es honesto, pero no ideal. Los textos en 37 idiomas no los ha leído ningún hablante nativo. Si hablas sueco, turco o polaco y encuentras un error en la ficha de Lanternly, me alegrará recibir tu correo.
Si empezara de nuevo, desde el primer día tendría un archivo fuente y un script de comprobación, antes incluso de la primera traducción. El resto de este trabajo se repite una y otra vez, y se le puede confiar a un script.



