FOS Localization
Versión 1.0.1 · requiere FOS Essentials Core 1.0.0 o posterior
Traduce los textos y las imágenes de un mundo de VRChat a tantos idiomas como quieras, editados en una tabla de verdad en lugar de en dos arrays sin relación, con ida y vuelta en CSV para quienes traducen y con el idioma elegido recordado entre visitas. Requiere FOS Essentials Core 1.0.0.
Puesta en marcha
Sección titulada «Puesta en marcha»- Crea un GameObject vacío y añade Add Component > FOS Essentials > Localization > Locale Manager.
- Rellena Language codes (
en,fr,es,de) y Language names (English,Français,Español,Deutsch). El primero es el idioma pivote al que recurren todos los demás, así que pon primero aquel en el que escribes el mundo. - Abre FOS Essentials > FOS Localization > Translation Table y añade tus claves.
- En cada texto de tu interfaz, añade Add Component > FOS Essentials > Localization > Localized Text, apúntalo al gestor y dale su clave.
- Para el selector de idioma, añade Language Button a cada botón, uno por idioma. Su
inspector conecta el
OnClickpor ti.
Componentes
Sección titulada «Componentes»| Componente | Función |
|---|---|
FOSLocaleManager |
Uno por mundo. Guarda los idiomas, la tabla y el idioma actual. |
FOSLocalizedText |
Enlaza una clave con un TMP_Text o un Text heredado. |
FOSLocalizedImage |
Cambia un sprite según el idioma. |
FOSLanguageButton |
Cambia el mundo a un idioma, con resalte opcional de seleccionado. |
Todo aquí es local. Ninguna variable sincronizada, ningún tráfico de red, ninguna propiedad de objeto. Dos jugadores uno al lado del otro no tienen por qué leer el mismo idioma, y sincronizar la elección significaría que uno la pierde cada vez que el otro hace clic.
La tabla de traducción
Sección titulada «La tabla de traducción»FOS Essentials > FOS Localization > Translation Table, o el botón del inspector del
gestor. Una fila por clave, una columna por idioma, y las celdas vacías van coloreadas
para que un hueco se vea en lugar de tener que buscarlo.
| Color | Significado |
|---|---|
| Rojo | El primer idioma está vacío. Nada a lo que recurrir: el mundo mostrará #clave. |
| Ámbar | Otro idioma está vacío. El mundo recurre al primer idioma. |
El primer idioma declarado es el pivote: es al que recurren todos los demás. Pon primero aquel en el que realmente escribes el mundo.
La barra de herramientas filtra por texto — la búsqueda también mira dentro de las traducciones, así que una frase vista en el juego basta para encontrar su clave — y Untranslated only reduce la tabla a las filas que aún necesitan trabajo.
Por qué la tabla no está en el inspector
Sección titulada «Por qué la tabla no está en el inspector»Las claves y las traducciones se guardan en dos arrays, ocultos del inspector a
propósito. La rejilla es plana: la traducción j de la clave i está en
i × idiomas + j. Una clave añadida a mano en el array, sin su fila de celdas, desplaza
un lugar todos los textos siguientes: sin error, sin nada visible en pantalla y sin forma
de reconstruir el original. La ventana es por tanto el único camino de escritura, y
mantiene ambos arrays acompasados.
Añadir o quitar un idioma en el inspector sí está bien: el gestor detecta el desajuste y repara la rejilla, moviendo cada traducción a su nueva posición.
Export CSV escribe toda la tabla, una fila por clave, una columna por idioma, con los códigos de idioma como cabeceras. Import CSV la vuelve a leer.
La importación es una fusión, nunca un reemplazo:
- Una clave presente en el archivo pero no en la tabla se añade.
- Una clave de la tabla ausente del archivo se deja intacta.
- Una columna cuya cabecera no corresponde a ningún idioma declarado se ignora: una columna de comentarios no cuesta nada.
- Una celda vacía nunca sobrescribe una traducción existente.
Así, un solo idioma puede salir a revisión y volver sin ningún riesgo para los demás, y quien devuelva una columna a medias no destruye nada.
El archivo se escribe en UTF-8 con BOM. Sin él, Excel abre el archivo en la página de códigos local y destroza todos los acentos, que es con diferencia la forma más habitual de estropear un viaje de ida y vuelta de traducción.
Las claves
Sección titulada «Las claves»Una clave es un identificador, no una frase: menu.title, rules.adult.warning,
teleport.button.spawn. Ponles prefijo por área para que una familia quede junta al
ordenar la tabla — el botón Sort ordena las claves alfabéticamente llevándose sus
traducciones, y eso es lo que hace visible al miembro que falta de una familia.
Una clave ausente aparece como #la.clave en el juego. Es deliberado: un hueco de
traducción tiene que notarse, y una etiqueta en blanco nunca se nota.
Los saltos de línea se escriben \n en la tabla. Un campo de inspector no admite un salto
de línea real, y un viaje por CSV no lo sobreviviría.
El idioma del jugador
Sección titulada «El idioma del jugador»VRChat no le dice a un mundo en qué idioma está el cliente de un jugador. No existe API para ello, así que ninguna herramienta puede detectarlo, esta incluida. El jugador llega en el idioma por defecto y cambia a mano.
Lo que sí se puede hacer es recordar su elección. Con Remember the choice activado, el
idioma se escribe en los PlayerData de VRChat y se restaura en la siguiente visita a
este mundo.
- Nada sale del mundo y nada se comparte con otros jugadores.
- La elección se guarda por el código del idioma, nunca por su índice, así que reordenar o insertar un idioma no mueve a todo el mundo en silencio.
- Un idioma retirado del mundo desde la última visita deja al jugador en el idioma por defecto en lugar de en ninguno.
Los PlayerData no se pueden leer en Start. El idioma por defecto se aplica de
inmediato y el guardado lo sustituye en OnPlayerRestored, y por eso quien vuelve puede
ver un fotograma en el idioma por defecto.
El coste
Sección titulada «El coste»La búsqueda se resuelve una sola vez, en Start: cada FOSLocalizedText recuerda el
índice de su clave y no vuelve a buscar jamás. Un cambio de idioma pasa a ser una lectura
indexada por texto.
Buscar por nombre en cada cambio — la forma obvia de escribir esto — cuesta textos × claves comparaciones de cadenas cada vez que alguien pulsa una bandera. En una interfaz de tableta con cien etiquetas y doscientas claves, son veinte mil comparaciones de cadenas por clic, en Udon.
Los componentes se registran solos en el gestor, así que no hay ninguna lista que rellenar a mano ni nada que actualizar cuando una página gana una etiqueta.
Scripting
Sección titulada «Scripting»| Llamada | En | Efecto |
|---|---|---|
FOSSetLanguage(int) |
FOSLocaleManager |
Cambia de idioma y guarda la elección |
FOSCurrentLanguage() |
FOSLocaleManager |
Índice del idioma mostrado |
FOSIndexOfLanguage(string) |
FOSLocaleManager |
Índice de un código de idioma, -1 si es desconocido |
FOSIndexOfKey(string) |
FOSLocaleManager |
Índice de una clave, -1 si es desconocida. Llámalo una vez |
FOSTextAt(int) |
FOSLocaleManager |
Traducción de una clave ya resuelta |
FOSText(string) |
FOSLocaleManager |
Traducción de una clave, búsqueda incluida |
FOSRegister(UdonSharpBehaviour) |
FOSLocaleManager |
Seguir los cambios de idioma |
SelectLanguage() |
FOSLanguageButton |
La acción del control |
Cualquier UdonSharpBehaviour puede llamar a FOSRegister(this) y exponer un
FOSApplyLanguage() público: se le avisará en cada cambio, exactamente igual que a los
componentes que vienen aquí. Ese es el punto de extensión para todo lo que este pack no
cubre: una fuente de audio por idioma, un reproductor de vídeo, la textura de un cartel.
Notas y límites
Sección titulada «Notas y límites»- Un gestor por mundo es el montaje previsto. Varios funcionan, pero cada uno tiene su tabla y su idioma actual, y quien cambie uno no cambia el otro.
- Los textos creados en ejecución no se recogen. Llama tú a
FOSRegistersobre ellos. - El idioma no se sincroniza, por diseño. Ver arriba.
- Quest y PC se comportan igual: no hay código específico de plataforma, ni podría haberlo, porque Udon se compila una sola vez para ambas.
