Jakie są najlepsze praktyki dotyczące projektowania wielojęzycznych baz danych? [Zamknięte]

193

Jaki jest najlepszy sposób na stworzenie wielojęzycznej bazy danych? Aby utworzyć zlokalizowaną tabelę dla każdej tabeli komplikuje projektowanie i zapytania, w innym przypadku dodanie kolumny dla każdego języka jest proste, ale nie dynamiczne, pomóż mi zrozumieć, co jest najlepszym wyborem dla aplikacji korporacyjnych

Arsen Mkrtchyan
źródło

Odpowiedzi:

223

To, co robimy, polega na utworzeniu dwóch tabel dla każdego obiektu wielojęzycznego.

Np. Pierwsza tabela zawiera tylko dane neutralne językowo (klucz podstawowy itp.), A druga tabela zawiera jeden rekord dla każdego języka, zawierający zlokalizowane dane oraz kod ISO języka.

W niektórych przypadkach dodajemy pole DefaultLanguage, abyśmy mogli wrócić do tego języka, jeśli nie są dostępne zlokalizowane dane dla określonego języka.

Przykład:

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>

Dzięki takiemu podejściu możesz obsługiwać tyle języków, ile potrzeba (bez konieczności dodawania dodatkowych pól dla każdego nowego języka).


Aktualizacja (14.12.2014): zapoznaj się z tą odpowiedzią , aby uzyskać dodatkowe informacje na temat implementacji używanej do ładowania danych wielojęzycznych do aplikacji.

M4N
źródło
15
co jeśli jedynym polem neutralnym dla języka jest identyfikator? i jak dokładnie wstawić odwołanie do klucza obcego podczas wstawiania wiersza?
Timo Huovinen,
4
To zabawne, że projektowałem schemat bazy danych dla wielojęzycznego CMS i miałem to pytanie w głowie. Wybrałem to podejście, zanim jeszcze zobaczyłem tę odpowiedź! Dzięki za tę odpowiedź!
Patrick Manser
5
Należy tutaj zauważyć, że albo nie będzie PK na tej tabeli, albo ID i Język muszą być złożonymi PK. Albo to, albo musisz dodać pole ProductTranslationId, prawdopodobnie jako tożsamość.
Daniel Lorenz,
1
@Luca: Odpowiedziałem na twoje pytanie, pokazując, jakich implementacji używam do ładowania danych.
M4N
1
@ AarónGutiérrez Cóż, zabawnie tworzysz tabelę z jedną kolumną o nazwie id: D. Aby wyjaśnić, każdy idreprezentuje znaczenie, do którego możesz dołączyć słowa z dowolnego języka w tabeli relacyjnej, więc otrzymujesz dwie tabele, meaning(id) i word(id, mean_id), idw wordtabeli reprezentuje słowo id, a idw meaningreprezentuje znaczenie, które jest uniwersalne.
Timo Huovinen,
18

Polecam odpowiedź wysłaną przez Martina.

Ale wydaje ci się, że martwisz się, że twoje zapytania stają się zbyt złożone:

Aby utworzyć zlokalizowaną tabelę dla każdej tabeli, projektowanie i tworzenie zapytań jest skomplikowane ...

Być może myślisz, że zamiast pisać proste zapytania takie jak to:

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

... musisz zacząć pisać takie zapytania:

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

Niezbyt ładna perspektywa.

Ale zamiast robić to ręcznie, należy opracować własną klasę dostępu do bazy danych, która wstępnie analizuje kod SQL zawierający specjalne znaczniki lokalizacji i konwertuje go na rzeczywisty kod SQL, który należy wysłać do bazy danych.

Korzystanie z tego systemu może wyglądać mniej więcej tak:

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

I jestem pewien, że możesz to zrobić jeszcze lepiej.

Kluczem do sukcesu jest równomierne nazwanie tabel i pól.

Rene Saarsoo
źródło
drugie pytanie brzmi: stworzyć jeden obiekt biznesowy dla produktu? lub stworzyć dwa ... w pierwszym przypadku łatwo jest pracować z tym elementem, w drugim łatwo napisać CMS
Arsen Mkrtchyan
14

Uważam, że tego rodzaju podejście działa dla mnie:

Produkt Produkt Szczegółowy kraj
========= ================== =========
ProductId ProductDetailId CountryId
- etc - ProductId CountryName
            CountryId Language
            ProductName - etc -
            Opis produktu
            - etc -

Tabela ProductDetail zawiera wszystkie tłumaczenia (dla nazwy produktu, opisu itp.) W językach, które chcesz obsługiwać. W zależności od wymagań aplikacji możesz chcieć rozbić tabelę kraju, aby używać także języków regionalnych.

Nacięcie
źródło
Wybrałem to samo podejście do projektu, nad którym obecnie pracuję, ponieważ moje różne lokalizacje zawierają bardzo szczegółowe informacje o systemach jednostek i środkach, które mają być wyświetlane użytkownikom.
califrench
8
Kraj i język (lokalizacje) to różne rzeczy. A kody języka ISO są naturalnymi kluczami, eliminujesz niepotrzebne dołączanie z języka na kraj.
gavenkoa
10

Używam następnego podejścia:

Produkt

ProductID OrderID, ...

Informacje o produkcie

ProductID Tytuł Nazwa LanguageID

Język

LanguageID Nazwa Kultura, ....

omoto
źródło
2

Rozwiązanie Martina jest bardzo podobne do mojego, ale jak poradziłbyś sobie z domyślnymi opisami, gdy pożądane tłumaczenie nie zostało znalezione?

Czy wymagałoby to instrukcji IFNULL () i kolejnej instrukcji SELECT dla każdego pola?

Tłumaczenie domyślne byłoby przechowywane w tej samej tabeli, gdzie flaga taka jak „isDefault” wskazuje, czy opis ten jest opisem domyślnym, na wypadek gdyby nie znaleziono żadnego dla bieżącego języka.

doM
źródło
1
@GorrillaApe: patrz odpowiedź na przykład, jak powrócić do domyślnego języka, jeśli żądany język nie został znaleziony: stackoverflow.com/a/27474681/19635
M4N