2010-02-09 15 views
50

Eventuali duplicati:
Schema for a multilanguage databaseQual è la migliore struttura di database per mantenere i dati multilingue?

Ecco un esempio:

[ products ] 
id (INT) 
name-en_us (VARCHAR) 
name-es_es (VARCHAR) 
name-pt_br (VARCHAR) 
description-en_us (VARCHAR) 
description-es_es (VARCHAR) 
description-pt_br (VARCHAR) 
price (DECIMAL) 

Il problema: ogni nuova lingua sarà necessario modificare la struttura della tabella.

Ecco un altro esempio:

[ products-en_us ] 
id (INT) 
name (VARCHAR) 
description (VARCHAR) 
price (DECIMAL) 

[ products-es_es ] 
id (INT) 
name (VARCHAR) 
description (VARCHAR) 
price (DECIMAL) 

Il problema: ogni nuova lingua sarà necessario la creazione di nuove tabelle e il campo "prezzo" è duplicata in ogni tavolo.

Ecco un altro esempio:

[ languages ] 
id (INT) 
name (VARCHAR) 

[ products ] 
id (INT) 
price (DECIMAL) 

[ translation ] 
id (INT, PK) 
model (VARCHAR) // product 
field (VARCHAR) // name 
language_id (INT, FK) 
text (VARCHAR) 

Il problema: fuc * ing duro?

+4

Il terzo metodo è più o meno corretto: cosa c'è di difficile da fare? –

+2

Il problema è che, con ogni soluzione trovata, troverai sempre un caso, quando devi modificare la tabella - cioè più lingue, lingue diverse, un altro campo ... –

+0

Puoi controllare questo link: http://www.gsdesign.ro/blog/multilanguage-database-design-approach/ sebbene leggere i commenti sia molto utile –

risposta

25

Il terzo esempio è in realtà il modo in cui il problema viene risolto di solito. Difficile, ma fattibile.

Rimuovere il riferimento al prodotto dalla tabella di conversione e inserire un riferimento alla traduzione dove è necessario (viceversa).

[ products ] 
id (INT) 
price (DECIMAL) 
title_translation_id (INT, FK) 

[ translation ] 
id (INT, PK) 
neutral_text (VARCHAR) 
-- other properties that may be useful (date, creator etc.) 

[ translation_text ] 
translation_id (INT, FK) 
language_id (INT, FK) 
text (VARCHAR) 

Come alternativa (non particolarmente una buona) si può avere un singolo campo e mantenere tutte le traduzioni là fuse insieme (come XML, per esempio).

<translation> 
    <en>Supplier</en> 
    <de>Lieferant</de> 
    <fr>Fournisseur</fr> 
</translation> 
+10

Cosa succede se la tabella del prodotto contiene diversi campi tradotti? Quando si recuperano prodotti, sarà necessario eseguire un join aggiuntivo per campo tradotto, con conseguenti gravi problemi di prestazioni. C'è anche una complessità addizionale (IMO) per inserire/aggiornare/eliminare. Il singolo vantaggio di questo è il minor numero di tavoli. Vorrei scegliere il metodo proposto da Gipsy King o Clément: penso che sia un buon equilibrio tra prestazioni, complessità e problemi di manutenzione. –

-1

Hanno molti e molti rapporti.

Hai la tabella dati, la tabella delle lingue e una tabella data_language.

Nella tabella data_language voi hanno

id, data_id, language_id

penso che potrebbe funzionare meglio per il vostro.

+0

@AntonioCS - La tabella "dati" non è la tabella "prodotto", giusto? –

+0

@TiuTalk lo è. In questo modo la tabella dei prodotti non deve sapere quali lingue ci sono, né la tabella delle lingue. È tutto nella tabella data_language (o in questo caso 'tabella product_language) – AntonioCS

10

Al fine di ridurre il numero di JOIN di, si potrebbe tenere separata la tradotti e non tradotti in 2 tavoli separati:

[ products ] 
id (INT) 
price (DECIMAL) 

[ products_i18n ] 
id (INT) 
name (VARCHAR) 
description (VARCHAR) 
lang_code (CHAR(5)) 
+0

@ Clément - Il problema qui è quando la tabella prodotti ottiene un nuovo campo ... Avrò bisogno di cambiare anche la tabella products_i18n. :/ –

+6

@TiuTalk - solo una della tabella otterrà il nuovo campo, se è un campo tradotto, va in 'products_i18n', altrimenti va in' prodotti'. In questo modo non duplichi alcuna informazione. –

+0

@ Clément: product.id è utente come FK in products_i18n.id o si utilizza la terza tabella di join? – CoR

-2

Usiamo questo concetto per il nostro webiste (600k viste al giorno) e (forse sorprendentemente) funziona. Certo insieme alla memorizzazione nella cache e all'ottimizzazione delle query.

[attribute_names] 
id (INT) 
name (VARCHAR) 

[languages_names] 
id (INT) 
name (VARCHAR) 

[products] 
id (INT) 
attr_id (INT) 
value (MEDIUMTEXT) 
lang_id (INT) 
+0

E per quanto riguarda i campi duplicati come il prezzo? –

+0

sicuramente funzionerebbe. – Rolf

3

Al mio $ DAYJOB usiamo gettext per I18N. Ho scritto un plug-in su xgettext.pl che estrae tutto il testo inglese dalle tabelle del database e li aggiunge al messaggio principale.pot.

Funziona molto bene: i traduttori gestiscono un solo file durante la traduzione: il file po. Non ci sono problemi con le voci del database quando si eseguono le traduzioni.

29

Simile al metodo 3:

[languages] 
id (int PK) 
code (varchar) 

[products] 
id (int PK) 
neutral_fields (mixed) 

[products_t] 
id (int FK) 
language (int FK) 
translated_fields (mixed) 
PRIMARY KEY: id,language 

Quindi per ogni tabella, fare un altro tavolo (nel mio caso con il suffisso "'t"), che contiene i campi tradotti. Quando si SELECT * FROM products, semplicemente ... LEFT JOIN products_t ON products_t.id = products.id AND products_t.language = CURRENT_LANGUAGE.

Non è difficile, e ti libera dai mal di testa.

2

[lingue] id (int PK) codice (varchar)

[products] 
id (int PK) 
name 
price 
all other fields of product 
id_language (int FK) 

Io in realtà uso questo metodo, ma nel mio caso, non è in un punto di vista del prodotto, per le varie pagine il mio CMS, questo lavoro è abbastanza buono.

Se si dispone di molti prodotti, potrebbe essere un problema aggiornare un singolo in 5 o 6 lingue ... ma si tratta di lavorare sul layout.

0

E la quarta soluzione?

[ products ] 
id (INT) 
language (VARCHAR 2) 
name (VARCHAR) 
description (VARCHAR) 
price (DECIMAL) 
*translation_of (INT FK)* 

* * Translation_of è FK di esso auto. Quando si aggiunge la lingua predefinita * translation_of * è impostato su Null. Ma quando aggiungi la seconda lingua * translation_of * prende l'id della lingua principale del prodotto.

SELECT * FROM products WHERE id = 1 AND translation_of = 1 

In questo caso si ottiene tutte le traduzioni per il prodotto con ID è 1.

SELECT * FROM products WHERE id = 1 AND translation_of = 1 AND language = 'pl' 

otteniamo unico prodotto in traduzione polacca. Senza secondo tavolo e JOINS.

+0

Questo è un approccio interessante. Mi piace la facilità di interrogazione, ma rompe il presupposto che mai l'entrata nella tabella del prodotto sia un prodotto, quindi bisogna tenerlo a mente. Consente inoltre di continuare a utilizzare i tipi appropriati (varchar, ecc.) Per i campi. – Rolf

+0

Stavo pensando di implementare esattamente la stessa cosa in questo momento, ma non ho trovato questa soluzione da nessun'altra parte. Vedo che il tuo post è del 2011. Hai avuto problemi con questo? Pensi ancora che sia una buona soluzione? Grazie. – tabacitu

+0

@tabacitu Hai provato questo? Com'è l'intero schema db? Come va su inserire, aggiornare, cancellare ...? – CoR

Problemi correlati