Cuando desarrollamos para dispositivos móviles, hemos de tener en cuenta que probablemente nuestro programa será usado en diferentes países por usuarios de varias lenguas. Una herramienta para facilitar el uso de nuestro programa a dichos usuarios es traducir nuestra aplicación al idioma local de cada usuario. Este proceso es conocido como Internacionalización (I18N) y Localización (L10N). Para saber más sobre cómo implementar esto en LibGDX, puedes consultar su Wiki oficial.
Por otro lado, una de las opciones que nos brinda LibGDX es poder trabajar con fuente tipográficas TrueType (.ttf) mediante la extensión gdx-freetype. Para saber más sobre cómo usar este tipo de fuente, puedes consultar la Wiki oficial de LibGDX.
Al combinar las dos herramientas anteriores (I18N / L10N y fuentes TTF), nos encontraremos con que:
- Cada idioma utiliza un determinado alfabeto. Esto es, de forma resumida, el conjunto de letras o grafías que se utilizan para representar el lenguaje de forma escrita.
- Normalmente, una fuente tipográfica soporta sólo un determinado conjunto de letras o grafías.
Como consecuencia de los dos puntos anteriores, es probable que debamos utilizar más de una fuente TTF para poder representar nuestro programa en determinados idiomas. A continuación, mostraremos un caso de uso tomando como ejemplo los idiomas Español y Ruso; aunque se puede trabajar con otros alfabetos de formas similar.
Importante:
- Esto no es un tutorial sobre cómo usar internacionalización o localización. Simplemente se muestra cómo dibujar textos en LibGDX a partir de fuentes tipográficas TrueTypeFont (.TTF).
- Gdx-freetype trabaja con textos en UTF-8, por lo tanto hemos de usar esta codificación en los archivos de nuestro proyecto.
- Puede obtener el código fuente desde GitHub.
Creación del proyecto (gdx-freetype)
Para empezar a trabajar el primer paso es la creación del proyecto de LibGDX. Como sabemos que vamos a trabajar con fuentes TTF, marcamos la extensión gdx-freetype para que Gradle importe las dependencias necesarias en nuestro proyecto.
En nuestro caso llamaremos al proyecto Gdx-Freetype-Example. A tener en cuenta:
- En este proyecto no usaremos la librería de físicas Box2d. Por tanto desmarcamos esta opción.
- Habilitamos la extensión Freetype, en el apartado Extensions.
- Freetype no soporta el proyecto Html. Por lo tanto también es necesario desmarcar este proyecto.

Los valores que hemos usado para este proyecto de ejemplo son:
- Name:
Gdx-Freetype-Example - Package:
com.pixnbgames.gdx_freetype_example - Game class:
GdxGameFreetypeExampleGame
Si lo hemos hecho bien, al importar el proyecto en nuestro IDE podremos ver como se importan las dependencias de gdx-freetype:

Seleccionando fuentes tipográficas
Hemos dicho que trabajaremos con los idiomas Español y Ruso. Para este ejemplo, simplemente vamos a imprimir en pantalla un mensaje de bienvenida:
- Español: ¡Hola Mundo!
- Ruso: Привет мир!
Si observamos el mensaje traducido al ruso puede parecernos un tanto extraño. Esto se debe a que mientras que el Español utiliza el alfabeto latino, el Ruso utiliza una variante del alfabeto cirílico.
Normalmente, una fuente tipográfica no soportará todos los alfabetos existentes, por lo que nos veremos obligados a seleccionar varias fuentes dependiendo del idioma que queramos representar. Para nuestro caso, usaremos las siguientes fuentes:
- Español: Goodfish Font Family
- Ruso: Imperial One
Añadir las fuentes a nuestro proyecto de LibGDX
Cuando descarguemos estas fuentes tipográficas, podemos tener más de un archivo TTF en cada una de ellas. Cada uno de estos archivos se corresponderá con un estilo de la fuente (negrita, cursiva, …). Para este ejemplo sólo tomaremos un archivo de cada fuente («goodfish rg.ttf» para Goodish y «Imperial Web.ttf» para Imperial One).
Los archivos TTF son un recurso más de nuestro proyecto y por tanto los agregamos a la carpeta «assets/» del proyecto android. Para una mejor organización de los recursos, podemos crear una carpeta específica, por ejemplo con el nombre «fonts/«, dentro del directorio «assets/» e incluir ahí nuestras fuentes tipográficas:

Generar fuentes TTF para LibGDX
Para poder renderizar texto con nuestras fuentes TTF, necesitamos primero generar fuentes Bitmap. Para centralizar la generación de fuentes, nos crearemos una clase FontFactory, en la que tendremos el código necesario para generar la fuente en función del Locale del usuario. El código de la clase FontFactory es demasiado largo para pegarlo aquí entero, así que lo iremos viendo por partes.
En primer lugar, tenemos dos variables estáticas de tipo String con los nombres de los archivos TTF:
13 14 | public static final String SPANISH_FONT_NAME = "fonts/goodfish rg.ttf"; public static final String RUSSIAN_FONT_NAME = "fonts/Imperial Web.ttf"; |
Después, tendremos una variable que contendrá los caracteres rusos. ¿Por qué? Por defecto, LibGDX generará los caracteres contenidos en la cadena FreeTypeFontGenerator.DEFAULT_CHARS. Dado que este String sólo contiene los caracteres latinos, si queremos generar otro tipo de caracteres hemos de decir explícitamente cuales son. En este ejemplo, usaremos la siguiente cadena con el alfabeto ruso:
17 18 19 | public static final String RUSSIAN_CHARACTERS = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ" + "абвгдеёжзийклмнопрстуфхцчшщъыьэюя" + "1234567890.,:;_¡!¿?\"'+-*/()[]={}"; |
Las fuentes generadas se almacenan en dos variables locales:
24 25 | private BitmapFont esFont; private BitmapFont ruFont; |
El siguiente método se encarga de generar la fuentes Bitmap:
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | private BitmapFont generateFont(String fontName, String characters) { // Configure font parameters FreeTypeFontParameter parameter = new FreeTypeFontParameter(); parameter.characters = characters; parameter.size = 24; // Generate font FreeTypeFontGenerator generator = new FreeTypeFontGenerator( Gdx.files.internal(fontName) ); BitmapFont font = generator.generateFont(parameter); // Dispose resources generator.dispose(); return font; } |
y será llamado desde el método initialize() tal que así:
37 38 39 40 41 42 43 44 | public void initialize() { // If fonts are already generated, dispose it! if (esFont != null) esFont.dispose(); if (ruFont != null) ruFont.dispose(); esFont = generateFont(SPANISH_FONT_NAME, FreeTypeFontGenerator.DEFAULT_CHARS); ruFont = generateFont(RUSSIAN_FONT_NAME, RUSSIAN_CHARACTERS); } |
Por último, usaremos el método getFont() para obtener la fuente en función del lenguaje usado por el Locale recibido por parámetro:
77 78 79 80 81 | public BitmapFont getFont(Locale locale) { if ("es".equals(locale.getLanguage())) return esFont; else if ("ru".equals(locale.getLanguage())) return ruFont; else throw new IllegalArgumentException("Not supported language"); } |
Dibujar textos en pantalla
En nuestra clase principal, GdxGameFreetypeExampleGame, dibujaremos el mensaje «¡Hola Mundo!» en español y ruso. Para ello declaramos los mensajes en dos variables estáticas:
14 15 | public static final String SPANISH_MESSAGE = "¡Hola Mundo!"; public static final String RUSSIAN_MESSAGE = "Привет мир!"; |
Además tendremos dos variables donde almacenaremos los Locale español y ruso:
21 22 | private Locale esLocale; private Locale ruLocale; |
En el método create(), inicializamos nuestra factoría de fuentes y los Locale de España y Rusia:
25 26 27 28 29 30 31 32 33 34 | public void create () { batch = new SpriteBatch(); // Initialize FontFactory FontFactory.getInstance().initialize(); // Initialize locales esLocale = new Locale("es", "ES"); ruLocale = new Locale("ru", "RU"); } |
Sólo nos queda dibujar desde el método render():
37 38 39 40 41 42 43 44 45 46 47 | public void render () { // Clear screen Gdx.gl.glClearColor(0, 0, 1, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // Draw with fonts batch.begin(); FontFactory.getInstance().getFont(esLocale).draw(batch, SPANISH_MESSAGE, 110.f, 150.f); FontFactory.getInstance().getFont(ruLocale).draw(batch, RUSSIAN_MESSAGE, 70.f, 100.f); batch.end(); } |
Resultado
El resultado de ejecutar el código anterior será algo así:
Como se puede ver, el mensaje se muestra correctamente en los dos idiomas; cada uno utilizando la fuente que hemos definido.
Mejoras:
Las siguientes posibles mejoras no se han tratado para no hacer el tutorial aun más extenso 🙂
- Aunque en este ejemplo mostramos la cadena en idiomas distintos, lo normal si tenemos una aplicación localizada es cargar sólo el idioma actual del usuario, con lo cual sólo sería necesario generar una fuente cada vez.
- Hay fuentes tipográficas preparadas para soportar múltiples alfabetos. Utilizando alguna de estas fuentes nos ahorraremos el tener que buscar una distinta para cada idioma soportado. Además, tener sólo un archivo .TTF también hará que nuestras aplicaciones ocupen menos espacio. Algo muy apreciado en dispositivos móviles.
Código fuente
Podéis encontrar todo el código fuente utilizado en GitHub.
