Quali sono le migliori pratiche per la progettazione di database multilingue? [chiuso]


193

Qual è il modo migliore per creare un database multilingue? Creare una tabella localizzata per ogni tabella sta rendendo complessa la progettazione e l'interrogazione, in altri casi aggiungere una colonna per ogni lingua è semplice ma non dinamico, per favore aiutatemi a capire qual è la scelta migliore per le applicazioni aziendali



Risposte:


223

Quello che facciamo è creare due tabelle per ogni oggetto multilingue.

Ad esempio, la prima tabella contiene solo dati indipendenti dalla lingua (chiave primaria, ecc.) E la seconda tabella contiene un record per lingua, contenente i dati localizzati più il codice ISO della lingua.

In alcuni casi aggiungiamo un campo DefaultLanguage, in modo da poter ricorrere a quella lingua se non sono disponibili dati localizzati per una lingua specifica.

Esempio:

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 questo approccio, puoi gestire tutte le lingue necessarie (senza dover aggiungere campi aggiuntivi per ogni nuova lingua).


Aggiornamento (2014-12-14): dai un'occhiata a questa risposta , per alcune informazioni aggiuntive sull'implementazione utilizzata per caricare dati multilingue in un'applicazione.


15
cosa succede se l'unico campo neutro in termini di lingua è l'id? e come si inserisce esattamente il riferimento della chiave esterna quando si inserisce una riga?
Timo Huovinen,

4
È divertente, stavo progettando uno schema di database per un CMS multilingue e avevo anche questa domanda nella mia testa. Ho scelto questo approccio, prima ancora di vedere questa risposta! Grazie per questa risposta!
Patrick Manser,

5
Una cosa da notare qui è che non ci sarebbe nessun PK su questa tabella o ID e Language dovrebbe essere il PK composito. O quello, o è necessario aggiungere un campo ProductTranslationId, probabilmente come identità.
Daniel Lorenz,

1
@Luca: ho risposto alla tua domanda, mostrando quali implementazioni utilizzo per caricare i dati.
M4N,

1
@ AarónGutiérrez Beh, stranamente crei una tabella con una singola colonna chiamata id: D. Per spiegare, ognuno idrappresenta un significato a cui è possibile associare parole da qualsiasi lingua in una tabella relazionale, in modo da ottenere due tabelle, meaning(id) e word(id, meaning_id), idnella wordtabella rappresenta la parola id, la idin meaningrappresenta il significato che è universale.
Timo Huovinen,

18

Consiglio la risposta inviata da Martin.

Ma sembri preoccupato che le tue domande diventino troppo complesse:

Creare una tabella localizzata per ogni tabella sta rendendo complessa la progettazione e l'interrogazione ...

Quindi potresti pensare che invece di scrivere semplici query come questa:

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

... dovresti iniziare a scrivere domande del genere:

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

Non è una prospettiva molto carina.

Ma invece di farlo manualmente dovresti sviluppare la tua classe di accesso al database, che pre-analizza il codice SQL che contiene il tuo markup di localizzazione speciale e lo converte nel codice SQL effettivo che dovrai inviare al database.

L'uso di quel sistema potrebbe assomigliare a questo:

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

E sono sicuro che puoi fare ancora meglio.

La chiave è avere tabelle e campi denominati in modo uniforme.


l'altra domanda è: creare un oggetto business per il prodotto? o crearne due ... nel primo caso è facile lavorare con quell'elemento, nel secondo facile scrivere CMS
Arsen Mkrtchyan,

14

Trovo che questo tipo di approccio funzioni per me:

Prodotto Prodotto Dettagli Paese
========= ================== =========
ProductId ProductDetailId CountryId
- etc - ProductId CountryName
            Lingua CountryId
            ProductName - ecc. -
            Descrizione del prodotto
            - eccetera -

La tabella ProductDetail contiene tutte le traduzioni (per nome prodotto, descrizione ecc.) Nelle lingue che si desidera supportare. A seconda delle esigenze della tua app, potresti voler suddividere la tabella Paese per usare anche le lingue regionali.


Ho scelto lo stesso approccio per un progetto a cui sto attualmente lavorando perché le mie diverse localizzazioni contengono informazioni molto specifiche sui sistemi di unità e le misure da mostrare agli utenti.
Califrench,

8
Paese e lingua (locali) sono cose diverse. E i codici ISO della lingua sono chiavi naturali, elimini l'unione non necessaria da una lingua all'altra.
gavenkoa,

10

Sto usando il prossimo approccio:

Prodotto

ProductID OrderID, ...

Informazioni sul prodotto

ProductID Titolo Nome LanguageID

linguaggio

LanguageID Nome Cultura, ....


2

La soluzione di Martin è molto simile alla mia, tuttavia come gestiresti le descrizioni predefinite quando la traduzione desiderata non viene trovata?

Ciò richiederebbe un IFNULL () e un'altra istruzione SELECT per ciascun campo?

La traduzione predefinita sarebbe memorizzata nella stessa tabella, dove un flag come "isDefault" indica se quella descrizione è la descrizione predefinita nel caso in cui non sia stata trovata nessuna per la lingua corrente.


1
@GorrillaApe: vedere questa risposta per un esempio su come tornare alla lingua predefinita, se la lingua desiderata non è stata trovata: stackoverflow.com/a/27474681/19635
M4N
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.