Skip to content

Internacionalización ​

La internacionalización en Infernus se centra principalmente en la conversión de conjuntos de caracteres, no en la traducción multilingüe. Si bien $t puede servir para necesidades de traducción, la función principal es garantizar el intercambio correcto de datos entre el servidor (UTF-8) y el cliente del jugador (conjuntos heredados como ISO-8859-1 o GBK). La mayoría de los servidores atienden solo una región, por lo que es posible que no necesite traducción alguna — pero al menos debe comprender la internacionalización de jugadores para evitar texto ilegible.

Extensión de VSCode ​

infernus-starter incluye un archivo de recomendación de extensiones (.vscode/extensions.json). Se recomienda encarecidamente que haga clic en instalar cuando VSCode lo solicite, para poder ver los datos de internacionalización fácilmente durante el desarrollo.

i18n-ally-custom-framework.yml y settings.json ya están configurados para la extensión.

Ejemplo ​

Definición de paquetes de idioma ​

Los paquetes de idioma son archivos .json. Se utilizan claves en estructura de árbol para organizar los datos de traducción.

Las cadenas pueden contener %s como marcadores de posición para valores dinámicos.

Paquete de idioma chino ​

json
{
  "server": {
    "running": "成功运行由 node.js 强力驱动的 omp 服务器",
    "connection": "连接信息: %s - %s : %s"
  }
}

Paquete de idioma inglés ​

json
{
  "server": {
    "running": "Successfully running an omp server powered by node.js",
    "connection": "connection information: %s - %s : %s"
  }
}

Instancia ​

Cree una instancia de I18n con new I18n("clave de región predeterminada", paqueteDeIdioma).

Normalmente solo necesita la función $t.

$t("clave de traducción", [arreglo de marcadores], clave de región) devuelve el texto traducido para la configuración regional indicada.

Cuando no hay marcadores de posición, pase null, undefined o un arreglo vacío.

Omitir el tercer parámetro usa la configuración regional predeterminada.

ts
import { I18n } from "@infernus/core";

// Paquetes de idioma internacionalizados en JSON
import zh_CN from "./locales/zh_CN.json";
import en_US from "./locales/en_US.json";

const locales = {
  zh_CN,
  en_US,
};

export const { $t } = new I18n("en_US", locales);

console.log($t("server.running"));
console.log($t("server.connection", ["127.0.0.1", "8080", "123456"]));
console.log($t("server.connection", ["127.0.0.1", "8080", "123456"], "zh_CN"));

Funciones útiles ​

La clase I18n también proporciona varios métodos estáticos prácticos para conversiones de conjuntos de caracteres:

  • encodeToBuf
    • Convierte una cadena en un arreglo de bytes en el conjunto de caracteres especificado.
  • decodeFromBuf
    • Convierte un arreglo de bytes en una cadena en el conjunto de caracteres especificado.
  • getValidStr
    • Extrae una cadena válida de un arreglo de bytes — el primer byte 0 marca el final de la cadena.

Internacionalización del jugador ​

Cada instancia de jugador tiene dos propiedades para la internacionalización: charset (conjunto de caracteres) y locale (región). Valores predeterminados:

ts
class Player {
  charset = "ISO-8859-1";
  locale = "en_US";
}

Normalmente $t combina la región del jugador para obtener los datos del paquete de idioma correspondiente.

ts
// Suponiendo que tiene una instancia de jugador
console.log($t("server.incoming", ["127.0.0.1", "8080", "123456"], player.locale));

Para cambiar el idioma o el conjunto de caracteres de un jugador, modifique sus propiedades charset y locale. Asegúrese siempre de que charset sea correcto. Puede adivinar la región del jugador por su dirección IP, o pedirle que introduzca una cadena específica y comparar bytes para determinar el conjunto de caracteres.

supportAllNickname ​

CONSEJO

Por defecto, el servidor del juego solo permite letras, números y guiones bajos en los nombres de usuario.

OMP proporciona nuevas API para habilitar o deshabilitar valores de byte específicos (0–255) en los nombres de usuario.

GameMode.supportAllNickname() aprovecha estas API para permitir que todos los nombres de usuario internacionales — incluyendo caracteres chinos y otros nombres no ASCII — se conecten.

ts
import { GameMode } from "@infernus/core";

GameMode.onInit(({ next }) => {
  GameMode.supportAllNickname();
  return next();
});

Cómo funciona ​

ADVERTENCIA

El intercambio bidireccional de datos de conjuntos de caracteres funciona correctamente solo si el conjunto de caracteres del jugador está configurado adecuadamente.

Si se configura un conjunto de caracteres incorrecto, tanto el servidor como el cliente recibirán texto ilegible.

Infernus utiliza iconv-lite para la conversión de conjuntos de caracteres y polyfill.amx para interceptar las retrollamadas del gamemode, devolviéndolas como arreglos de bytes decimales.

Las funciones del servidor al cliente como SendClientMessage, SendClientMessageToAll, ShowPlayerDialog y CreateDynamic3DTextLabel convierten datos UTF-8 al conjunto de caracteres del jugador, asegurando una visualización correcta.

Las funciones del cliente al servidor como OnText, OnPlayerCommandText y OnDialogResponse también se someten a conversión de conjunto de caracteres, garantizando un intercambio de datos correcto.

CONSEJO

A pesar de la conversión de conjunto de caracteres, los caracteres UTF-8 no presentes en el conjunto de caracteres del jugador seguirán apareciendo ilegibles (por ejemplo, como ?). Esto es una limitación del código subyacente del cliente original de SA. Por ejemplo, un cliente ISO-8859-1 que recibe emojis o caracteres chinos mostrará texto ilegible.

Para GameText/TextDraw, Infernus no aplica la conversión de charset del jugador: estas dos funciones codifican el texto con el charset que les pases (win1252 por defecto en GameText y ISO-8859-1 en TextDraw). El cliente elige los glifos de la textura de su fuente según el valor del byte (similar a los sprites CSS en el desarrollo frontend) en lugar de decodificar los bytes como texto. Algunos mods de cliente (por ejemplo, parches de idioma chino) reemplazan la fuente y esperan bytes UTF-8; en ese caso pasa charset: "utf8".

El ruso funciona con el mismo mecanismo desde el otro lado: un russifier es un mod de localización rusa que el jugador instala en su cliente; redibuja la fuente del juego, colocando las letras cirílicas en las celdas que la fuente original reserva para caracteres latinos acentuados. @infernus/rustext aporta la mitad del servidor, reescribiendo el texto saliente de las RPC de GameText, TextDraw y Menu para que los bytes cp1251 caigan en las celdas de ese mod. Pasa charset: "cp1251" de forma explícita (los valores por defecto anteriores convierten el cirílico en ? antes de que el paquete pueda verlo) y ajusta el RussifierType al paquete que el jugador tenga realmente instalado, porque cada paquete coloca las letras de forma distinta (SanLtd es el valor por defecto, junto con OneC, Rush, MG y otros). El paquete no incluye ningún recurso de russifier. El texto enviado a todos los jugadores (GameText.forAll) no lleva id de jugador y no se convierte.

La Edición Definitiva de SA usa UTF-8 internamente. Si OMP agrega soporte en línea para ella en el futuro, no debería ser necesario ningún manejo adicional.

Caracteres ilegibles en la terminal ​

Si encuentra caracteres ilegibles en la terminal al usar librerías de registro como pino.js, pruebe una de las siguientes soluciones.

Para usuarios de PowerShell, ejecute el siguiente comando (válido solo para la sesión actual).

Para hacer el cambio permanente, agregue el comando a su $PROFILE.

powershell
$OutputEncoding = [Console]::InputEncoding = [Console]::OutputEncoding = New-Object System.Text.UTF8Encoding

Para usuarios de cmd, use el siguiente comando para iniciar su servidor OMP:

sh
cmd /c "chcp 65001 > nul & omp-server"

Estos comandos cambian el conjunto de caracteres de la terminal a UTF-8.

Para otros entornos, busque soluciones por su cuenta.