Per implementare il supporto multilingue nel tuo modello di dati, non è necessario reinventare la ruota. Questo articolo ti mostrerà i diversi modi per farlo e ti aiuterà a scegliere quello che funziona meglio per te.
Il concetto di localizzazione è fondamentale per lo sviluppo di un'applicazione software, in particolare quando l'ambito di tale applicazione è globale. Il supporto per più lingue è l'aspetto principale da considerare; un design del database che supporta un'applicazione multilingue ti consente di diversificare i tuoi mercati di destinazione e raggiungere così molti più clienti. Inoltre, una tale progettazione di database potrebbe far parte della tua strategia a lungo termine per la progettazione di sistemi pronti per la localizzazione.
La chiave per incorporare il supporto multilingue nella tua applicazione è farlo in un modo che non aumenti drasticamente i costi di sviluppo o manutenzione. Poiché la modellazione del database è una parte inseparabile del processo di sviluppo del software, devi pensare alla migliore strategia di progettazione del modello di dati per fornire supporto multilingue alla tua applicazione.
Un modello di dati adeguato dovrebbe consentire di modificare l'applicazione o aggiungere nuove funzionalità mantenendo il supporto multilingue, senza aggiungere ulteriori sforzi o costi. Dovrebbe anche consentire di incorporare nuove lingue senza toccare l'applicazione; devi solo aggiungere i dati di traduzione corrispondenti al database.
Implementazione semplice vs flessibilità e funzionalità
Esistono diversi approcci alla creazione di una progettazione di database per applicazioni multilingua. Ognuno ha i suoi vantaggi e svantaggi. Quelli più facili da implementare offrono meno flessibilità e meno funzionalità; quelli che offrono maggiore flessibilità e funzionalità hanno implementazioni più complesse.
Il mio consiglio qui è di scegliere sempre quelli che offrono più funzionalità e flessibilità , anche se sono più costosi da implementare. A volte commettiamo l'errore di pensare che un'applicazione sia troppo piccola, che non valga la pena implementare schemi complessi per risolvere cose come il supporto multilingua. Ma alla fine, quell'applicazione crescerà e ci pentiremo di aver optato per l'approccio "rapido e sporco" che sembrava più semplice e meno costoso.
L'ideale per implementare funzionalità accessorie in un'applicazione, che si tratti di supporto multilingue, registrazione delle modifiche, autenticazione utente o altro, è che quella funzionalità abbia il proprio sottoschema e la sua logica incapsulata in componenti riutilizzabili. In questo modo, sia la funzionalità dell'accessorio che il suo sottoschema possono essere incorporati in qualsiasi nuova applicazione con il minimo sforzo.
Uno strumento intelligente per la progettazione di database e la modellazione dei dati come Vertabelo è di grande aiuto per la gestione efficiente di schemi e sottoschemi. Inoltre, dai un'occhiata a questi suggerimenti per una migliore progettazione del database e assicurati di seguirli tutti. Prima di iniziare a disegnare il tuo diagramma ER, ti suggerisco di prendere in considerazione questa serie essenziale di suggerimenti per la modellazione del database.
Alcune soluzioni per la progettazione di database multilingue interessanti (ma sconsigliabili)
Il più semplice, ma meno consigliato
Iniziamo con il modo meno consigliato ma più semplice per implementare un database di applicazioni multilingue. Ti consente di risolvere rapidamente la necessità di supportare un'applicazione multilingue, ma ti porterà problemi quando l'applicazione cresce in termini di funzionalità o copertura geografica.
Questa semplice strategia consiste nell'aggiungere una colonna aggiuntiva per ogni colonna di testo da tradurre e per ogni lingua in cui i testi devono essere tradotti.
Ad esempio, in Movies
tabella sottostante, c'è un OriginalTitle
campo. Viene aggiunta un'ulteriore colonna del titolo per ciascuna lingua da tradurre:
IDFilm | Titolo originale | Titolo_sp | Titolo_it | Titolo_fr |
---|---|---|---|---|
1 | Duro a morire | Duro de matar | Trappola di cristallo | Piege de cristal |
2 | Ritorno al futuro | Volver al futuro | Ritorno al futuro | Ritorna verso il futuro |
3 | Jurassic Park | Parque jurasico | Giurassico parco | Parco giurassico |
L'applicazione deve ottenere i dati descrittivi dalla colonna corrispondente alla lingua selezionata dall'utente. Quando devi aggiungere una nuova lingua, devi aggiungere una colonna aggiuntiva alla tabella per contenere i testi tradotti nella nuova lingua. Devi anche adattare l'applicazione per riconoscere la lingua e le colonne aggiunte.
Questa soluzione non richiede JOIN complicati per ottenere i testi tradotti, né record duplicati, ma solo la replica delle colonne del contenuto del testo. Ma la sua applicabilità è limitata alle situazioni in cui devono essere tradotte solo poche tabelle.
Ad esempio, supponi di avere un Products
tabella e un Processes
tavolo. Ognuno di essi ha un campo Descrizione che necessita di traduzione; sembra abbastanza facile, giusto? Ma se l'intera applicazione (incluse tutte le opzioni di menu, i messaggi di errore, ecc.) deve essere multilingue, questa soluzione non è applicabile.
Più versatile, ma anche sconsigliabile
Continuando con l'idea di mantenere le traduzioni all'interno della stessa tabella, un'alternativa alla precedente opzione consiste nell'allargare i campi di testo. Questo ci consentirebbe di archiviare tutte le traduzioni nello stesso campo, organizzandole in una struttura dati (ad esempio un documento XML o un oggetto JSON). Di seguito abbiamo un esempio:
ID film | Titolo originale | Traduzioni |
1 | Duro a morire | [ {"language":"sp", "title":"Duro de matar"}, {"language":"it", "title":"Trappola di cristallo"}, {"language":"fr", "title":"Piège de cristal"} ] |
2 | Ritorno al futuro | [ {"language":"sp", "title":"Volver al futuro"}, {"language":"it", "title":"Ritorno al futuro"}, {"language":"fr", "title":"Retour vers le futur"} ] |
3 | Jurassic Park | [ {"language":"sp", "title":"Parque jurásico"}, {"language":"it", "title":"Giurassico parco"}, {"language":"fr", "title":"Parc jurassique"} ] |
Questa opzione non richiede colonne aggiuntive, ma aggiunge complessità. Le query di dati ora devono essere in grado di elaborare e interpretare correttamente la struttura dei dati utilizzata per il supporto multilingua. Ad esempio, se vengono utilizzati JSON o XML per archiviare le traduzioni, le query SQL devono utilizzare una versione SQL che supporti il tipo di dati scelto.
Il seguente comando SQL utilizza MS SQL Server OPENJSON()
funzione per utilizzare i contenuti delle Translations
campo come tabella subordinata:
SELECT m.MovieId, m.OriginalTitle, t.TranslatedTitle FROM Movies AS m CROSS APPLY OPENJSON(m.Translations) WITH ( language char(2) '$.language', TranslatedTitle varchar(100) '$.title’ ) AS t WHERE t.language = 'fr';
Poiché non ci sono funzioni o operatori per manipolare dati formattati JSON o XML in SQL standard, sei costretto a scrivere le tue query per un particolare RDBMS se vuoi usare questa tecnica per memorizzare i testi tradotti. Ad esempio, la query precedente non è supportata da MySQL. Se hai bisogno di leggere i dati JSON nei Movies
tabella con MySQL, scriveresti questa query:
SELECT m.MovieId, m.OriginalTitle, JSON_EXTRACT(m.Translations, '$.title') AS TranslatedTitle FROM Movies AS m WHERE JSON_EXTRACT(m.Translations. '$.language') = 'fr';
Memorizzazione del testo tradotto in record diversi
Puoi anche scegliere di utilizzare record diversi per ogni lingua. Devi però rassegnarti a perdere la normalizzazione:gli stessi dati si ripetono in più record, in cui varia solo la traduzione.
IDFilm | LinguaId | Titolo |
---|---|---|
1 | it | Duro a morire |
1 | sp | Duro de matar |
1 | esso | Trappola di cristallo |
1 | fr | Piege de cristal |
2 | it | Ritorno al futuro |
2 | sp | Volver al futuro |
2 | esso | Ritorno al futuro |
Con questa opzione, puoi creare viste di ogni tabella che restituiscono solo le righe in una determinata lingua:
CREATE VIEW Movies_en AS SELECT MovieId, Title FROM Movies WHERE LanguageId = 'en'; CREATE VIEW Movies_sp as SELECT MovieId, Title FROM Movies WHERE LanguageId = 'sp';
Quindi, per interrogare la tabella, puoi utilizzare una vista diversa a seconda della lingua di traduzione di destinazione. Ma la normalizzazione del modello è persa e la manutenzione delle tabelle è inutilmente complessa.
Memorizzazione del testo tradotto in tabelle separate
Un modo per archiviare i testi tradotti senza rompere il modello relazionale è avere una tabella dei dettagli per ogni tabella contenente i testi da tradurre. La tabella subordinata contenente le traduzioni deve avere gli stessi campi chiave della tabella madre, più un campo indicante la lingua di traduzione.
Una tabella subordinata con traduzioni deve avere gli stessi campi chiave della tabella madre, più un campo che indica la lingua di traduzione.
Questa opzione consente di incorporare nuove lingue senza alterare la struttura della tabella. Non richiede la generazione di informazioni ridondanti o l'interruzione della normalizzazione del modello.
Lo svantaggio di questa opzione è che richiede la creazione di una tabella subordinata per ogni tabella che memorizza i dati testuali che richiedono la traduzione. Tuttavia, l'idea di memorizzare le traduzioni in tabelle correlate ci avvicina al modo più consigliabile di progettare un database multilingue.
La soluzione universale:un sottoschema di traduzione
Affinché un'applicazione e il suo database siano veramente multilingue, tutti i testi devono avere una traduzione in ciascuna lingua supportata, non solo i dati di testo in una tabella particolare. Ciò si ottiene con un sottoschema di traduzione in cui vengono archiviati tutti i dati con contenuto testuale che possono raggiungere gli occhi dell'utente.
Nelle applicazioni Web destinate all'uso in lingue diverse, un sottoschema di traduzione è una necessità, non un'opzione. Qualsiasi altra cosa comporterà complessità che renderanno impossibile la corretta manutenzione dell'applicazione.
La chiave per mantenere le traduzioni in uno schema separato è mantenere un catalogo indicizzato con tutti i testi che necessitano di traduzione, siano essi descrizioni di entità, messaggi di errore o opzioni di menu. L'idea è che nessun testo che possa raggiungere gli occhi dell'utente è memorizzato in nessuna tabella al di fuori di questo sottoschema.
Un modo per organizzare il catalogo delle traduzioni è utilizzare tre tabelle:
- Una tabella principale delle lingue.
- Una tabella di testi in lingua originale.
- Una tabella di testi tradotti.
Schema per un catalogo di traduzione universale.
Nella tabella principale delle lingue inseriamo semplicemente un record per ogni lingua supportata dal modello dati. Ognuno ha un codice ID e un nome:
LinguaId | NomeLingua |
---|---|
it | Inglese |
sp | Spagnolo |
esso | Italiano |
fr | francese |
La tabella di testo registra tutti i testi che richiedono la traduzione. Ogni record ha un ID arbitrario, il testo originale e l'ID della lingua originale.
Nel TextContent
tabella, il testo originale e l'ID della lingua originale non sono strettamente necessari. Ma semplificano le query che non richiedono la traduzione. Ad esempio, quando si eseguono query di analisi statistica o di controllo di gestione (che di solito sono disponibili solo per utenti che comprendono la lingua originale) le query possono essere semplificate utilizzando i testi predefiniti (non tradotti).
I testi originali sono utili anche per chi deve riempire la tabella dei testi tradotti. L'inserimento dei dati di traduzione può essere effettuato tramite una mini-applicazione che mostra il testo originale e le traduzioni in tutte le lingue disponibili. È anche possibile generare informazioni per il sottoschema di traduzione tramite un processo automatico utilizzando un'API di traduzione.
Collegamento con lo schema principale
Nello schema principale dell'applicazione, le colonne con valori di testo da tradurre vengono sostituite da ID che puntano alla tabella dei testi tradotti:
Lo schema principale è collegato allo schema di traduzione tramite tabelle con testi che necessitano di traduzione.
È possibile lasciare il campo di testo originale in alcune delle tabelle principali dello schema per facilitare le query in cui non è richiesta la traduzione, anche se ciò genera informazioni ridondanti. Ad esempio, potremmo mantenere il ProductDescription
campo nel Products
tabella per facilitare le interrogazioni statistiche o per popolare le dimensioni di un data warehouse, lasciando da parte il sottoschema di traduzione quando non è necessario.
- Progettazione di database multilingue:fallo una volta e fallo bene
Abbiamo visto diverse alternative per la creazione di una progettazione di database multilingue. Alcuni sono più facili e veloci da implementare. L'ultima soluzione è un po' più complessa, ma ti dà molta più flessibilità. Ti farà risparmiare anche problemi quando arriva il momento di mantenere l'applicazione e il database. Quindi, a lungo termine, sarà molto meno costoso.
A volte, il percorso più breve nella progettazione di database ti porta a credere che risparmierai tempo e fatica. Ma quando lo scegli, stai trascurando il fatto che probabilmente dovrai scenderlo più volte. Se ignori le migliori pratiche per la progettazione di database multilingue, probabilmente finirai per fare lo stesso lavoro più e più volte.