[Ror-es] Multi - idiomas

Hari Seldon hari.seldon.developer at gmail.com
Wed Sep 5 22:56:17 GMT 2007


Bueno, para muestras, unos cuántos botones.

schema.yml de symfony:

# START entity ARCHIVO
  archivo:
    _attributes: { phpName: Archivo, isI18N: true, i18nTable: archivo_i18n }
    id: { type: integer, required: true, autoIncrement: true, primaryKey:
true }
    path: { type: varchar, size: 255 }
    mime_type: { type: varchar, size: 20 }
    created_at: { type: timestamp }
    updated_at: { type: timestamp }
  archivo_i18n:
    _attributes:{ phpName: ArchivoI18n }
    id: { type: integer, required: true, primaryKey: true, foreignTable:
archivo, foreignReference: id, onDelete: cascade }
    culture: { isCulture: true, type: varchar, size: 7, required: true,
primaryKey: true }
    nombre: { type: varchar, size: 150 }
    descripcion: { type: varchar, size: 255 }
# END entity ARCHIVO

Que se traduce en el siguiente SQL (para MySQL):


CREATE TABLE `archivo`
(
	`id` INTEGER  NOT NULL AUTO_INCREMENT,
	`path` VARCHAR(255),
	`mime_type` VARCHAR(20),
	`created_at` DATETIME,
	`updated_at` DATETIME,
	PRIMARY KEY (`id`)
)Type=InnoDB;

CREATE TABLE `archivo_i18n`
(
	`id` INTEGER  NOT NULL,
	`culture` VARCHAR(7)  NOT NULL,
	`nombre` VARCHAR(150),
	`descripcion` VARCHAR(255),
	PRIMARY KEY (`id`,`culture`),
	CONSTRAINT `archivo_i18n_FK_1`
		FOREIGN KEY (`id`)
		REFERENCES `archivo` (`id`)
		ON DELETE CASCADE
)Type=InnoDB;



Lógicamente la clave de la tabla auxiliar es el 'id' del archivo y
'culture'....

(Habrá quién proponga que exista una tabla "Cultures" con todos los
lenguajes, y se hagan tablas de cruce entre lenguajes y modelos concretos...
Pero la simplificación que se usa en symfony de usar las convenciones de
locales me parece mejor, nos ahorra querys y es perfectamente válida -por
que no tiene sentido que pongamos dos cultures iguales con valores de nombre
diferentes...-)


Desde luego, la solución que propone Globalize:


http://www.saimonmoore.net/2007/3/17/globalize-internal-storage-mechanism

Me parecen ambas, un tanto "malas"; en la anterior a la 1.2, guardaba las
traducciones en una tabla de traducciones:

Before the for-1.2 release, Globalize used an external table
(globalize_translations) to store translations

Y ahora lo guarda mediante el "“Internal Storage Mechanism”, dónde está
duplicando campos dentro de una misma tabla.

Si miramos la primera opción de Globalize, vemos que la tabla de
traducciones puede llegar a ser _enorme_, pues tal y cómo lo explican ahí,
esa tabla es para toda la aplicación... Entiendo que para todos los modelos
O;)

La segunda, implica que un cambio de número de idiomas en tu aplicación,
tengas que volver a tocar tu código; si eres tu el que mantiene el sitio
web, sí, ganas en rapidez a la hora de ejecutar consultas... Pero como no lo
mantengas tu, y quieras dar una solución multilenguaje a tu cliente final,
pues no me parece una solución acertada...

Ciertamente, la segunda solución es la más KISS; pero... El precio, a mi
entender, es alto.

Si queremos dotar a nuestra aplicación de un soporte multilenguaje REAL,
debería de ser posible agregar/eliminar lenguajes con facilidad a la misma,
sin que tengamos que tocar el código fuente; por ello, sigo pensando que la
solución de Symfony es, por el momento, superior.

Y si lo que queremos es hacer la traducción de pocos términos, francamente,
con un gettext se va que chuta... Sin tanta complicación.

Repito, pensando en la escalabilidad, entiendo que la solución de utilizar
dos tablas es bastante superior; y en cuánto a rendimiento, la diferencia
...

Database changed
mysql> select * from archivo;
....
83 rows in set (0.0161 sec)



mysql> SELECT * FROM archivo INNER JOIN archivo_i18n ON archivo.id =
archivo_i18n.id
....
83 rows in set (0.0181 sec)

Vamos, no creo que la diferencia de rendimiento sea un hándicap tan grande.

Un saludo

De: Iñigo Sola Núñez [mailto:isola009 at gmail.com] 
Enviado el: miércoles, 05 de septiembre de 2007 21:25
Para: hari.seldon.developer at gmail.com; La lista sobre Ruby On Rails
(rubyonrails.com) en castellano
Asunto: Re: [Ror-es] Multi - idiomas


Esta solución que propones, Iñigo, me parece una cagada, con perdón. 

Para gustos los colores, pero veamos tu propuesta... 

Es el planteamiento que hace Globalize, y me parece HORROROSO. 

De paso, ya que estamos, aprovecho yo también para preguntar a ver si hay
algo parecido a lo que existe en Symfony (seguramente exista)

No me consta 

En Symfony, si se tiene el modelo:

Producto { id, nombre, descripcion, created_at }

Y lo quieres internacionalizar, creas una tabla i18n, así:

Producto { id, created_at }
Producto_i18n { culture, producto_id, nombre, descripcion } 

Si nos ponemos un poco quisquillosos, salta a la vista que tu solución es
menos eficiente. Almacenas  un campo extra para la  relación, por no hablar
de los join que habría que hacer en tiempo de ejecución. 

Dónde en el modelo Producto_i18n es PK clave principal "culture" (es, etc 
etc...) y "producto_id" FK clave externa

No se si entiendo tu planteamiento. ¿'Culture' es la clave principal? De ser
así no podrás tener mas de un producto de cada idioma.
De cualquier forma no entiendo esta desnomarlización que propones, sobre
todo no veo las ventajas que aporta,... no las veo. 

Es evidente que así tenemos un gestor de productos dinámico en cuánto a
lenguajes posibles de traducción. 

Y lo mejor de todo, es que esto se integra en el ActiveRecord de Symfony; si
por ejemplo queremos el nombre del producto en español, haríamos:

$producto = ProductoPeer::getByPK(1);
$producto->setCulture('es'); 
echo $producto->getNombre();

En inglés:
$producto->setCulture('en');
echo $producto->getNombre();

Puedes conseguir lo mismo diseñandote un sencillo procedimiento a nivel de
modelo. (y ahorrándote hacer joins) 

Y así sucesivamente...

¿Existe algo así para RoR? Yo creo que tiene que existir... El caso es 
¿dónde? ;)

No me costa que exista. 

Un saludo a todos y gracias 

Igualemente.





More information about the Ror-es mailing list