¿Cuáles son las mejores prácticas para el diseño de bases de datos en varios idiomas? [cerrado]

193

¿Cuál es la mejor manera de crear una base de datos en varios idiomas? Crear una tabla localizada para cada tabla hace que el diseño y las consultas sean complejas; en otro caso, agregar una columna para cada idioma es simple pero no dinámico, ayúdenme a comprender cuál es la mejor opción para las aplicaciones empresariales

Arsen Mkrtchyan
fuente

Respuestas:

223

Lo que hacemos es crear dos tablas para cada objeto multilingüe.

Por ejemplo, la primera tabla contiene solo datos de idioma neutral (clave principal, etc.) y la segunda tabla contiene un registro por idioma, que contiene los datos localizados más el código ISO del idioma.

En algunos casos, agregamos un campo DefaultLanguage, para que podamos recurrir a ese idioma si no hay datos localizados disponibles para un idioma específico.

Ejemplo:

Table "Product":
----------------
ID                 : int
<any other language-neutral fields>


Table "ProductTranslations"
---------------------------
ID                 : int      (foreign key referencing the Product)
Language           : varchar  (e.g. "en-US", "de-CH")
IsDefault          : bit
ProductDescription : nvarchar
<any other localized data>

Con este enfoque, puede manejar tantos idiomas como sea necesario (sin tener que agregar campos adicionales para cada nuevo idioma).


Actualización (14/12/2014): consulte esta respuesta para obtener información adicional sobre la implementación utilizada para cargar datos multilingües en una aplicación.

M4N
fuente
15
¿Qué pasa si el único campo de idioma neutral es el id? y ¿cómo inserta exactamente la referencia de clave externa al insertar una fila?
Timo Huovinen
44
Es curioso, que estaba diseñando un esquema de base de datos para un CMS multilingüe y también tenía esta pregunta en mi cabeza. ¡Elegí este enfoque, incluso antes de ver esta respuesta! Gracias por esta respuesta!
Patrick Manser
55
Una cosa a tener en cuenta aquí es que no habrá PK en esta tabla o ID y el idioma debe ser el PK compuesto. O eso, o necesita agregar un campo ProductTranslationId, probablemente como una identidad.
Daniel Lorenz
1
@Luca: Respondí tu pregunta, mostrando qué implementación (s) utilizo para cargar los datos.
M4N
1
@ AarónGutiérrez Bueno, curiosamente creas una tabla con una sola columna llamada id: D. Para explicar, cada uno idrepresenta un significado al que puede adjuntar palabras de cualquier idioma en una tabla relacional, por lo que obtiene dos tablas, meaning(id) y word(id, meaning_id), iden la wordtabla representa la palabra id, el iden el meaningrepresenta El significado es universal.
Timo Huovinen
18

Recomiendo la respuesta publicada por Martin.

Pero parece que le preocupa que sus consultas se vuelvan demasiado complejas:

Crear una tabla localizada para cada tabla hace que el diseño y las consultas sean complejas ...

Por lo tanto, podría estar pensando que, en lugar de escribir consultas simples como esta:

SELECT price, name, description FROM Products WHERE price < 100

... tendrías que empezar a escribir consultas así:

SELECT
  p.price, pt.name, pt.description
FROM
  Products p JOIN ProductTranslations pt
  ON (p.id = pt.id AND pt.lang = "en")
WHERE
  price < 100

No es una perspectiva muy bonita.

Pero en lugar de hacerlo manualmente, debe desarrollar su propia clase de acceso a la base de datos, que analiza previamente el SQL que contiene su marcado de localización especial y lo convierte al SQL real que deberá enviar a la base de datos.

Usar ese sistema podría verse más o menos así:

db.setLocale("en");
db.query("SELECT p.price, _(p.name), _(p.description)
          FROM _(Products p) WHERE price < 100");

Y estoy seguro de que puedes hacerlo aún mejor.

La clave es tener sus tablas y campos nombrados de manera uniforme.

Rene Saarsoo
fuente
la otra pregunta es, ¿crear un objeto comercial para el producto? o para crear dos ... en el primer caso es fácil trabajar con ese elemento, en 2º CMS fácil de escribir
Arsen Mkrtchyan
14

Creo que este tipo de enfoque funciona para mí:

Producto Producto Detalle País
========= ================== =========
ProductId ProductDetailId CountryId
- etc - ProductId CountryName
            CountryId Language
            Nombre del producto - etc. -
            Descripción del producto
            - etc -

La tabla ProductDetail contiene todas las traducciones (para el nombre del producto, la descripción, etc.) en los idiomas que desea admitir. Dependiendo de los requisitos de su aplicación, es posible que desee desglosar la tabla de países para usar también idiomas regionales.

Mella
fuente
Elegí este mismo enfoque para un proyecto en el que estoy trabajando actualmente porque mis diferentes configuraciones regionales contienen información muy específica sobre los sistemas de unidades y las medidas que se mostrarán a los usuarios.
califrench
8
El país y el idioma (locales) son cosas diferentes. Y los códigos de idioma ISO son claves naturales, elimina la unión innecesaria de un idioma a otro.
gavenkoa
10

Estoy usando el siguiente enfoque:

Producto

ProductID OrderID, ...

Información del producto

ProductID Título Nombre LanguageID

Idioma

ID de idioma Nombre Cultura, ....

omoto
fuente
2

La solución de Martin es muy similar a la mía, sin embargo, ¿cómo manejaría las descripciones predeterminadas cuando no se encuentra la traducción deseada?

¿Eso requeriría un IFNULL () y otra instrucción SELECT para cada campo?

La traducción predeterminada se almacenaría en la misma tabla, donde un indicador como "isDefault" indica si esa descripción es la descripción predeterminada en caso de que no se haya encontrado ninguna para el idioma actual.

doM
fuente
1
@GorrillaApe: vea esta respuesta para ver un ejemplo de cómo volver al idioma predeterminado, si no se encontró el idioma deseado: stackoverflow.com/a/27474681/19635
M4N