كيفية دعم نهج اللاعب متعدد اللغات في مخطط قاعدة البيانات؟
-
22-09-2019 - |
سؤال
أريد أن تدعم قاعدة البيانات الخاصة بي لغات متعددة لجميع قيم النص في جداولها.
إذن ما هو أفضل طريقة للقيام بذلك؟
edit1 ::
على سبيل المثال
أنا هذا الجدول "الشخص":
ID int
FirstName nvarchar(20)
LastName nvarchar(20)
Notes nvarchar(max)
BirthDate date
...........
لذلك إذا أردت أن يدعم برنامجي لغة جديدة "دع القول الفرنسية".
هل يجب أن أضيف عمودًا جديدًا في كل مرة أضيف فيها لغة جديدة؟ لذا فإن طاولة "شخصي" ستبدو هكذا
ID int
FirstName_en nvarchar(20)
FirstName_fr nvarchar(20)
LastName_en nvarchar(20)
LastName_fr nvarchar(20)
Notes_en nvarchar(max)
Notes_fr nvarchar(max)
BirthDate date
...........
أم يجب أن أضيف 2 جدولين جديدين جديدين لللغات والآخر لقيم "person_languages"؟
لذلك سيبدو هذا: " اللغات " الطاولة:
ID int
Lang-symbol nvarchar(4)
" شخص " الطاولة:
ID int
BirthDate Date
وأخيرا " person_translation " الطاولة:
LangID int
PersonID int
Translation nvarchar(max)
أو هناك شيء أفضل ؟؟
.
المحلول
لقد اضطررت إلى التعامل مع هذا في قاعدة بيانات Questionaire. هناك حاجة إلى ترجمة أسئلة متعددة بلغات متعددة (اللغة الإنجليزية ، اليابانية ، الصينية).
حددنا أولاً جميع الأعمدة النصية التي سيتم طباعتها على أسئلة. على كل هذه ، سنحتاج إلى أن نكون قادرين على تخزين الترجمة. لكل جدول له أعمدة نصية تتطلب ترجمات ، أنشأنا بعد ذلك جدول _translations ، ولدينا مفتاحًا خارجيًا للإشارة إلى المفتاح الأساسي للجدول الأصلي ، ومفتاحًا خارجيًا إلى جدول لغتنا ، ثم عمود Unicode لكل حقل نص وهذا يتطلب الترجمة. في هذه الأعمدة النصية ، سنقوم بتخزين الترجمات لكل لغة نحتاجها.
لذلك سيبدو الاستعلام النموذجي:
select p.id
, pt.product_name
, pt.product_description
from product p
inner join product_translations pt
on p.id = pt.product_id
and 'fr' = pt.language_code
لذلك ، دائمًا ما ينضم إلى واحد إضافي (لكل جدول) للحصول على الترجمات.
أود أن أشير إلى أننا لم نتعامل إلا مع كمية محدودة من الجداول ، لذلك لم تكن مشكلة كبيرة للحفاظ على بضع ٪ من الجداول الإضافية.
لقد فكرنا في إضافة أعمدة للغة الجديدة ، لكننا قررنا ضده لمجموعة من الأسباب. بادئ ذي بدء ، لم يكن عدد اللغات التي سيتم دعمها معروفة ، ولكن يمكن أن تكون كبيرة (10 ، 20 لغة أو ربما أكثر). إلى جانب حقيقة أن معظم الجداول لديها 3 أعمدة قابلة للقراءة البشرية المتميزة على الأقل ، سيتعين علينا إضافة العديد من الأعمدة النصية التي قد تؤدي إلى صفوف واسعة جدًا. لذلك قررنا عدم القيام بذلك.
نهج آخر اعتبرناه لجعل جدول "تسمية" كبير واحد ، وجود الأعمدة:
(table_name ، id_of_table ، column_name ، language_id ، translated_text)
بفعالية وجود جدول واحد لتخزين جميع الترجمات في أي مكان في قاعدة البيانات. لقد قررنا ذلك أيضًا ، لأنه سيؤدي إلى تعقيد استفسارات الكتابة (حيث أن كل عمود "عادي" سيؤدي إلى صف واحد في جدول الترجمة ، مما سيؤدي إلى الانضمام بفعالية إلى جدول الترجمة الكبير بالفعل إلى الجدول العادي (مرة واحدة لكل منهما العمود المترجم). لجدول المثال الخاص بك ، ستحصل على استفسارات مثل هذا:
select product.id
, product_name.translated_text product_name
, product_description.translated_text product_description
from product p
inner join translations product_name
on p.id = product_name.id
and 'product' = product_name.table_name
and 'product_name' = product_name.column_name
and 'fr' = product_name.language
inner join translations product_description
on p.id = product_name.id
and 'product' = product_description.table_name
and 'product_description' = product_description.column_name
and 'fr' = product_description.language
كما ترون ، في الأساس هذا النوع من التصميم الذي يشبه إلى حد كبير تصميم القيمة ، مما يجعله مرهقًا للاستعلام.
هناك مشكلة أخرى في هذا النهج الأخير وهي أنه من الصعب إنفاق القيود على النص المترجم (في حالتنا بشكل أساسي ، قيود أحادية). مع جدول منفصل للترجمات ، يمكنك بسهولة التغلب على هذه المشكلات.
نصائح أخرى
لقد قمت للتو بتنفيذ شيء يعمل بشكل جيد للغاية.
مثل العديد من الآخرين ، لم يكن لدي قائمة نظيفة للبدء بها ، وكانت جميع الجداول مستعدة لتخزين النص الإنجليزي.
لم أكن سعيدًا بشكل خاص بمضاعفة عدد الجداول ، أو الأعمدة لتحقيق قاعدة بيانات متعددة اللغات.
قررت استخدام XML كوسيلة لتخزين جميع الترجمات ، إلى حقل واحد:
<text>
<translation lang="EN-GB">good day</translation>
<translation lang="FR-FR">bonjour</translation>
</text>
على سبيل المثال ، بدأت بجدول يحمل اللغة الإنجليزية فقط:
ProductId INT
ProductName varchar(200)
ProductDescription varchar(1000)
ثم قمت بإنشاء الحقول متعددة اللغات:
ProductId INT
ProductNameTranslation xml
ProductDescriptionTranslation xml
إذا كنت تريد أن تكون قادرًا على الحصول على قيمة للقراءة فقط للحقول الأصلية ، فيمكنك ببساطة إضافة أعمدة محسوبة مستمرة:
ProductId INT
ProductNameTranslation xml
ProductDescriptionTranslation xml
ProductNameDefaultLang = dbo.GetDefaultLanguage(ProductNameTranslation)
ProductDescriptionDefaultLang = dbo.GetDefaultLanguage(ProductDescriptionTranslation)
في طبقة الأعمال/البيانات ، يتم تحويل حقل XML إلى درجة الأعمال من نوع القاموس ، مع كون المفتاح تعداد اللغة:
ProductName {
get {return this.ProductNameTranslation[selectedLanguage];}
set {...}
}
سمح لي هذا النهج بتجنب الاضطرار إلى إعادة عرض قاعدة البيانات تمامًا. وهذا يعني أيضًا تفاعلًا أقل مع قاعدة البيانات ، صف واحد يتم حفظه بدلاً من صف رئيسي واحد ، و 3 صفوف ترجمة.
كما أنه يتجنب مشكلة الاضطرار إلى التعامل مع الحالات التي لا يوجد فيها الصف الرئيسي صفوف ترجمة
تجدر الإشارة إلى أن XML لديها فهارس مخطط و XML لتعزيز الأداء.
هذا النهج مفيد للغاية حيث تريد القيام بتحويل اللغة بشكل تدريجي ، أي حقل واحد في وقت واحد.