IT이야기

다국어 데이터를 보관하기 위한 최적의 데이터베이스 구조

cyworld 2021. 10. 9. 14:39
반응형

다국어 데이터를 보관하기 위한 최적의 데이터베이스 구조는?


중복 가능성:
다국어 데이터베이스용 스키마

다음은 예입니다.

[ 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)

문제: 모든 새로운 언어는 테이블 구조를 수정해야 합니다.

다음은 또 다른 예입니다.

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

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

문제: 모든 새 언어는 새 테이블을 생성해야 하며 "가격" 필드는 모든 테이블에 복제됩니다.

다음은 또 다른 예입니다.

[ 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)

문제: 어렵다?


세 번째 예는 실제로 문제가 일반적으로 해결되는 방식입니다. 어렵지만 가능합니다.

번역 테이블에서 제품에 대한 참조를 제거하고 필요한 곳에 번역에 대한 참조를 두십시오(반대).

[ 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)

대안으로(특히 좋은 것은 아님) 단일 필드를 갖고 모든 번역을 함께 병합된 상태로 유지할 수 있습니다(예: XML).

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

방법 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

따라서 각 테이블에 대해 번역된 필드를 보유하는 다른 테이블(내 경우에는 "_t" 접미사 포함)을 만드십시오. 당신이 SELECT * FROM products, 단순히 ... LEFT JOIN products_t ON products_t.id = products.id AND products_t.language = CURRENT_LANGUAGE.

그렇게 어렵지 않고 두통을 피할 수 있습니다.


JOIN의 수를 줄이기 위해 2개의 별도 테이블에 번역된 것과 번역되지 않은 것을 별도로 유지할 수 있습니다.

[ products ]
id (INT)
price (DECIMAL)

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

내 $DAYJOB에서 우리는 I18N에 대해 gettext를 사용합니다. 데이터베이스 테이블에서 모든 영어 텍스트를 추출하여 마스터 messages.pot에 추가 하는 플러그인을 xgettext.pl에 작성했습니다 .

그것은 매우 잘 작동합니다 - 번역가는 번역을 할 때 오직 하나의 파일인 po 파일만 처리합니다. 번역을 할 때 데이터베이스 항목을 만지작거릴 필요가 없습니다.


[언어] id(int PK) 코드(varchar)

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

실제로 이 방법을 사용하지만 제 경우에는 제품의 관점에서 볼 때 CMS의 다양한 페이지에 대해 이 작업이 꽤 좋습니다.

제품이 많은 경우 5개 또는 6개 언어로 하나의 제품을 업데이트하는 것이 골칫거리일 수 있지만 레이아웃 작업의 문제입니다.


네 번째 솔루션은 어떻습니까?

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

*Translation_of*는 자체의 FK 입니다. 기본 언어를 추가할 때 *translation_of*는 Null로 설정됩니다. 그러나 두 번째 언어를 추가할 때 *translation_of*는 기본 제품 언어 ID를 사용합니다.

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

이 경우 id가 1인 제품에 대한 모든 번역을 얻습니다.

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

우리는 폴란드어 번역으로만 제품을 얻습니다. 두 번째 테이블과 JOINS가 없습니다.


다대다 관계를 갖습니다.

데이터 테이블, 언어 테이블 및 data_language 테이블이 있습니다.

data_language 테이블에는

아이디, 데이터 아이디, 언어 아이디

나는 그것이 당신을 위해 가장 잘 작동 할 수 있다고 생각합니다.


우리는 이 개념을 웹사이트(하루에 600k 조회수)에 사용하고 (놀랍게도) 작동합니다. 물론 캐싱 및 쿼리 최적화와 함께.

[attribute_names]
id (INT)
name (VARCHAR)

[languages_names]
id (INT)
name (VARCHAR)

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

ReferenceURL : https://stackoverflow.com/questions/2227985/whats-the-best-database-structure-to-keep-multilingual-data

반응형