Skip to content

Internacionalización (i18n) ​

La validación con @QRule de QuickModel produce mensajes de error como strings. Cuando tu aplicación soporta múltiples idiomas, puedes conectar cualquier librería i18n para traducir esos strings automáticamente — sin cambiar las definiciones de tus modelos.

Cómo funciona ​

Configura una función resolver en QConfig. Cada vez que una regla falla, QuickModel pasa el mensaje de error crudo (o clave) por el resolver antes de devolverlo al llamante:

typescript
import { QConfig } from 'quickmodel';

QConfig.configure({
	i18n: {
		resolver: (key) => miLibreriaI18n.traducir(key),
	},
});

El resolver se llama únicamente para reglas que fallan — nunca para las que pasan.

Ejemplo básico ​

typescript
QConfig.configure({
	i18n: {
		resolver: (key) => t(key), // cualquier función de traducción
	},
});

@Quick()
class UserModel extends QModel<IUser> {
	@QRule(
		(val: string) => val.length >= 3,
		'validation.name.minLength' // clave i18n
	)
	declare name: string;
}

const result = new UserModel({ name: 'Al' }).$qCheckRules();
// → { valid: false, errors: [{ field: 'name', message: 'El nombre debe tener al menos 3 caracteres' }] }
//   El resolver tradujo 'validation.name.minLength' para el locale activo

Integración con librerías i18n habituales ​

vue-i18n ​

typescript
import { createI18n } from 'vue-i18n';
import { QConfig } from 'quickmodel';

const i18n = createI18n({ ... });

QConfig.configure({
  i18n: {
    resolver: (key) => String(i18n.global.t(key)),
  },
});

react-i18next ​

typescript
import i18next from 'i18next';
import { QConfig } from 'quickmodel';

QConfig.configure({
	i18n: {
		resolver: (key) => i18next.t(key),
	},
});

Angular TranslateService ​

typescript
import { TranslateService } from '@ngx-translate/core';

export function setupQuickModelI18n(translate: TranslateService): void {
	QConfig.configure({
		i18n: {
			resolver: (key) => translate.instant(key),
		},
	});
}

Sin librería — mapa estático ​

typescript
const mensajes: Record<string, string> = {
	'validation.name.minLength': 'El nombre debe tener al menos 3 caracteres',
	'validation.email.format': 'Formato de email inválido',
};

QConfig.configure({
	i18n: {
		resolver: (key) => mensajes[key] ?? key, // fallback a la clave si no existe
	},
});

Estrategia 1 — Claves i18n en @QRule ​

Almacena claves de traducción en lugar de strings literales. El resolver las traduce en tiempo de ejecución:

typescript
@Quick()
class ProductModel extends QModel<IProduct> {
	@QRule((v: string) => v.length > 0, 'validation.title.required')
	@QRule((v: string) => v.length <= 200, 'validation.title.maxLength')
	declare title: string;

	@QRule((v: number) => v > 0, 'validation.price.positive')
	declare price: number;
}

Ventajas: El modelo es completamente agnóstico al locale. Cambiar las traducciones no requiere tocar el modelo.

Estrategia 2 — Resolver lazy () => string en @QRule ​

Pasa una función en lugar de un string. Se evalúa en el momento de checkRules(), tomando el locale actual:

typescript
import { t } from './i18n';

@Quick()
class UserModel extends QModel<IUser> {
	@QRule(
		(val: string) => val.length >= 3,
		() => t('validation.name.minLength') // evaluado en tiempo de validación
	)
	declare name: string;
}

Ventajas: No se necesita resolver global en QConfig.i18n. Funciona cuando distintas partes de la app tienen diferentes contextos de locale.

Estrategia 3 — Combinar ambas ​

Usa resolvers lazy en @QRule para mensajes de campo específicos, y un resolver global en QConfig.i18n como fallback universal para el resto de claves:

typescript
QConfig.configure({
	i18n: {
		resolver: (key) => t(key), // fallback global para todos los modelos
	},
});

@Quick()
class UserModel extends QModel<IUser> {
	@QRule(
		(val: string) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val),
		() => t('validation.email.format') // lazy, con locale actual
	)
	declare email: string;

	@QRule((v: string) => v.length >= 8, 'validation.password.minLength')
	declare password: string; // usa el resolver global vía QConfig
}

Patrón de pipe en Angular ​

En Angular puedes almacenar claves simples y aplicar | translate en los templates — sin resolver global:

typescript
@Quick()
class FormModel extends QModel<IFormData> {
	@QRule((v: string) => v !== '', 'FORM.NAME_REQUIRED')
	declare name: string;
}
html
<!-- Template: traduce la clave devuelta en e.message -->
<span *ngFor="let e of errors">{{ e.message | translate }}</span>

Reglas asíncronas e i18n ​

El resolver también se aplica a los errores de checkRulesAsync():

typescript
const result = await model.$qCheckRulesAsync();
// → errors[].message también pasa por el resolver

Referencia de API ​

SímboloDescripción
QConfig.configure({ i18n: { resolver } })Registra un resolver de mensajes global
resolver(key: string): stringRecibe el mensaje o clave crudo, devuelve el string traducido
@QRule(pred, 'clave')Usa una clave string como mensaje de error
@QRule(pred, () => string)Función lazy evaluada en tiempo de validación

Ver también ​