Во-первых, будьте очень внимательны к ограничениям. Для контента, созданного пользователями, вы ищете перевод сообщества (ошибочный), машинный перевод (ненадежный) или платные человеческие переводчики (дорого!), Если вы хотите локализовать материал, который ваши пользователи вводят в ваше приложение. Возможно, вы захотите попросить своих пользователей предоставить две версии - одну для вашей культуры по умолчанию (на английском?) И одну для их локализованной культуры, чтобы вы могли предоставить запасной перевод для других пользователей?
Во-вторых, будьте готовы к очень длительным миграциям базы данных ... если у вас есть четыре столбца текста в электронной таблице Excel, вам вдруг приходится вставлять каждое значение в вашу систему перевода, извлекать локализованный идентификатор и затем сохраните , что в таблице, которую вы фактически импортируете - и SELECT *
даст вам только идентификаторы фраз, которые вам нужно преобразовать обратно в строки, локализуя их в ваших таблицах перевода.
Тем не менее, вы можете локализовать множество справочных таблиц, раскрывающихся списков и т. Д., Которые управляются базой данных в типичном проекте. В других комментариях уже упоминалось о хранении значений StringId в базе данных, которые ссылаются на файлы внешних ресурсов или электронные таблицы, но если вы заинтересованы в том, чтобы хранить ВСЕ локализованный текст в базе данных вместе с самими данными, то этот подход может оказаться полезным.
Мы использовали таблицу под названием «Фраза», которая содержит идентификатор и содержимое по умолчанию (на английском языке) для каждого фрагмента текста в вашем приложении.
Ваши другие таблицы в итоге выглядят так:
CREATE TABLE ProductType (
Id int primary key,
NamePhraseId int, -- link to the Phrase containing the name of this product type.
DescriptionPhraseId int
)
Создайте вторую таблицу Культура, которая содержит конкретные и нейтральные культуры, которые вы поддерживаете. Для получения бонусных баллов реализуйте эту таблицу в виде дерева со ссылками (каждая запись культуры содержит обнуляемую ссылку ParentCultureCode), чтобы вы могли откатиться от определенных культур ("fr-CA" для канадского французского) к нейтральным культурам ("fr" если региональная локализация не существует), к вашей инвариантной / стандартной культуре (обычно 'en', потому что на ней так много говорят)
Ваши фактические переводы находятся в таблице LocalizedPhrase, которая выглядит следующим образом:
CREATE TABLE LocalizedPhrase (
PhraseId int primary key,
CultureCode varchar(8) primary key,
Content nvarchar(255) -- the actual localized content
)
Вы можете расширить эту модель, если хотите указать локализацию для мужчин и женщин:
CREATE TABLE GenderedLocalizedPhrase (
PhraseId int primary key,
CultureCode varchar(8) primary key,
GenderCode char(1) primary key, -- 'm', 'f' or '?' - links to Gender table
Content nvarchar(255)
)
Вы захотите кэшировать весь этот табличный граф в памяти и соответствующим образом изменить свои стратегии запросов / объединений - одним из подходов является кэширование локализаций внутри классов Phrase и переопределение метода ToString () объекта Phrase для проверки текущей культуры потоков. Если вы попытаетесь сделать это в своих запросах, вы понесете существенные потери производительности, и каждый запрос будет выглядеть так:
-- assume @MyCulture contains the culture code ('ca-FR') that we are looking for:
SELECT
Product.Id,
Product.Name,
COALESCE(ProductStatusLocalizedPhrase.Content, ProductStatusPhrase.Content) as ProductStatus,
COALESCE(ProductTypeLocalizedPhrase.Content, ProductTypePhrase.Content) as ProductType,
FROM Product
INNER JOIN ProductStatus ON Product.StatusId = ProductStatus.Id
INNER JOIN Phrase as ProductStatusPhrase ON ProductStatus.NamePhraseId = Phrase.Id
LEFT JOIN LocalizedPhrase as ProductStatusLocalizedPhrase
ON ProductStatus.NamePhraseId = ProductStatusLocalizedPhrase.Id and CultureCode = @MyCulture
INNER JOIN ProductType ON Product.TypeId = ProductType.Id
INNER JOIN Phrase as ProductTypePhrase ON ProductType.NamePhraseId = Phrase.Id
LEFT JOIN LocalizedPhrase as ProductTypeLocalizedPhrase
ON ProductType.NamePhraseId = ProductTypeLocalizedPhrase.Id and CultureCode = @MyCulture