2008-10-10 16 views
9

busco opiniones si el siguiente problema tal vez tiene una solución mejor/diferente/común:base de datos de localización


Tengo una base de datos de productos que contiene los nombres de los productos en Inglés (el idioma por defecto de esta aplicación) y necesito traducciones de los nombres si están disponibles.

Actualmente tengo esta configuración:

Una tabla de productos

CREATE TABLE products 
(
    id serial NOT NULL, 
    "name" character varying(255) NOT NULL, 
    CONSTRAINT products_pkey PRIMARY KEY (id) 
) 

y una mesa de localización de productos

CREATE TABLE products_l10n 
(
    product_id serial NOT NULL, 
    "language" character(2) NOT NULL, 
    "name" character varying(255) NOT NULL, 
    CONSTRAINT products_l10n_pkey PRIMARY KEY (product_id, language), 
    CONSTRAINT products_l10n_product_id_fkey FOREIGN KEY (product_id) 
     REFERENCES products (id) MATCH SIMPLE 
     ON UPDATE CASCADE ON DELETE CASCADE 
) 

y utilizo la siguiente consulta para recuperar una lista de los productos localizados (alemán en este caso) con el retorno a los nombres ingleses predeterminados:

SELECT p.id, COALESCE(pl.name, p.name) 
from products p LEFT 
JOIN products_l10n pl ON p.id = pl.product_id AND language = 'de'; 

El código SQL está en el dialecto postgres. Los datos se almacenan como UTF-8.

Respuesta

6

Se ve bien conmigo. Lo único que podría cambiar es la forma en que manejas los idiomas: probablemente debería ser una tabla separada. Por lo tanto, tendría:

CREATE TABLE products_l10n 
(
    product_id serial NOT NULL, 
    language_id int NOT NULL, 
    "name" character varying(255) NOT NULL, 
    CONSTRAINT products_l10n_pkey PRIMARY KEY (product_id, language), 
    CONSTRAINT products_l10n_product_id_fkey FOREIGN KEY (product_id) 
     REFERENCES products (id) MATCH SIMPLE 
     ON UPDATE CASCADE ON DELETE CASCADE 
    CONSTRAINT products_l10n_language_id_fkey FOREIGN KEY (language_id) 
     REFERENCES languages (id) MATCH SIMPLE 
     ON UPDATE CASCADE ON DELETE CASCADE 
) 

CREATE TABLE languages 
) 
    id serial not null 
    "language" character(2) NOT NULL 
) 

Además de eso, creo que tiene casi la mejor solución posible.

+2

La base de datos no debería poder optimizar un campo de caracteres (2) de todos modos como integral, ya que los códigos de idioma ISO 639-1 son más legibles en comparación con los enteros si hay problemas. – Fionn

+0

Pensé exactamente lo mismo. Sin embargo, en un segundo vistazo, usar una capa adicional tiene algunas ventajas: es posible enumerar todos los idiomas disponibles/configurados (útiles dentro de la GUI), puede eliminar un idioma completo (con restricciones DB) y previene los "errores tipográficos". Aunque esto último no debería importar al usar 2 códigos de char;) – kazu

0

Parece decente para mí.

Obviamente, debe poner el nombre localizado en una columna Unicode, que puede optar por poner el valor predeterminado en inglés en un campo ASCII (suponiendo que la base de datos lo admita). Puede ser mejor hacer Unicode por todas partes y "olvidarse" de ello.

+0

Han editado la pregunta - los datos están siempre en Unicode (UTF-8). – Fionn

1

Se ve bien - similar a mi técnica de localización preferida - ¿qué pasa con los caracteres anchos (japonés)? Siempre utilizamos nvarchar para manejar eso.

Lo que encontramos, sin embargo, en nuestra operación de compras internacionales, era que no había consistencia entre fronteras internacionales en los productos, ya que los proveedores en cada país eran diferentes, así que internacionalizamos/localizamos nuestra interfaz, pero las bases de datos estaban completamente distinto.

+0

Han editado la pregunta: los datos están siempre en Unicode (UTF-8). – Fionn

1

La única variación que puedo ofrecer es que también es posible que desee incluir la posibilidad de país/dialecto; por ejemplo, en lugar de solo inglés (en), use English US (en-US). De esta forma puede dar cuenta de las variaciones en todo momento (por ejemplo, la ortografía británica, el francés canadiense probablemente tenga diferencias con el francés hablado en Francia, etc.).

0

El único factor que complica que otros no hayan mencionado es el conjunto de códigos: ¿podrá manejar hebreo, árabe, ruso, chino o japonés? Si todo es Unicode, solo tiene que preocuparse por GB18030 (chino), que es (IIUC) un superconjunto de Unicode.

0

Cuando se trata de este tipo de cosas, utilizo para construir una tabla de producto que no contiene ningún nombre, y una tabla de traducción de producto que contiene solo nombres (y más, obviamente).

Entonces termino con este tipo de consulta:

 
SELECT 
    i.id, 
    i.price, 
    it.label 
FROM 
    items i 
    LEFT JOIN items_trans it 
     ON i.id=it.item_id AND it.lang_id=(
      SELECT lang_id 
      FROM items_trans 
      WHERE item_id=i.id 
      ORDER BY 
       (lang_id=1) DESC, 
       (lang_id=0) DESC 
      LIMIT 1 
     ) 

¿Qué opinas?

+1

No me gusta esta opción, porque en este caso no se garantiza que tenga al menos un valor predeterminado para los nombres que no están traducidos. – Tengiz