2009-09-01 2 views
8

В многоязычном приложении со справочными таблицами, как лучше всего обрабатывать переводы?Каков наилучший способ обработки I18N в справочных таблицах?

Например, для таблицы поиска страны пользователь США должен видеть названия английской страны, так как немецкий должен видеть немецкие имена. Но все же их идентификаторы должны быть одинаковыми.

я могу думать о следующем:

  • Добавить другую таблицу поиска для каждого языка
  • Использования одной таблицы поиска с несколькими записями для одной и той же страны, под флаг в соответствии с его языком.
  • Избавьтесь от всех таблиц поиска и сделать все Lookups программным кодом
  • [Любая другая идея, которую я не думал?]

ответ

8

Большой вопрос здесь - может перевод может быть изменен до конца пользователей?

Если ответ «НЕТ», пакеты ресурсов проще и быстрее использовать, чем таблицы. Вместо фактического текста ваши таблицы будут содержать ключ ресурса (или вы можете использовать первичный ключ для этой цели, если он текстовый, а не числовой), и соответствующий набор ресурсов будет содержать перевод.

Если ответ «ДА», вы должны хранить переводы в базе данных. Однако я нашел, что самый простой подход в этом сценарии состоит в том, чтобы имитировать вышеупомянутую функциональность пакета ресурсов в базе данных - например, иметь одну таблицу с столбцами «locale», «resource key», «resource value», которые будут использоваться всеми другими таблицами для поиска фактического локализованного текста.

3

Несвязанная презентация от программирования. Внутренне используйте идентификаторы для всего; при представлении пользователям, представить локализованные данные.

1

Я сделал многоязычное приложение один раз. Все должно было быть многоязычным, в том числе введенным пользователем контента, а также было легко сделать перевод на этом контенте.

Теперь, если его только для статического текста больше всего рекомендуют файлы ресурсов xml для этого. Я считаю, что это хорошо поддерживается платформой .NET.

Если он должен быть динамичным, то я таблица структура

Таблица ресурсных строк RESOURCEID Guid PK cultureCode Строка PK текст Строка

Это тогда позволило мне TODO каскад чтения на код культуры также. Так что если кто-то имел культуры код ан-нас, я мог бы сделать запрос, где я сделал

SELECT FROM ResourceStrings 
WHERE resourceId = <AND ID> AND cultureCode IS IN ('en','en-us') 
ORDER BY cultureCode DESC 

Таким образом, самый длинный код культуры вернется первым и наиболее специфичны. Теперь я бы рекомендовал это ТОЛЬКО, если вы разрешаете пользователям вводить текст и переводить его. Мне это нужно, потому что контент должен быть многоязычным, а также самим приложением.

0

Отметьте что-то вроде Adobe Source Libraries 'xstring структуры данных и алгоритмы. Локализация осуществляется с идентификатором для строки, а также контекстом, детализирующим локализацию. Таблицы локализации могут храниться в XML, а строки локализованы во время выполнения на основе контекста среды выполнения (язык, страна, платформа и т. Д.) Хотя сам код работает, я бы не стал рассматривать его качество. Тем не менее, понятия твердые.

1

В моем текущем проекте (пользовательском CMS, написанном на django) наше решение для моделей I18N основано на этом фрагменте примера: http://www.djangosnippets.org/snippets/855/, который я расширил, чтобы использовать его в шаблонах и интегрировать в интерфейс администрирования.

В принципе, содержимое каждого вида имеет две таблицы: одну с общими полями (например, категорию статей) и одну с переводимым контентом (название, тело, слизь - уникальная метка, используемая в URL-адресе и т. Д.). Очевидно, что существует общая взаимосвязь между общей моделью и моделью перевода. Вот пример автор дает:

class Article(models.Model): 
    author = models.CharField(max_length = 40) 

class ArticleI18N(I18NModel): 
    title = models.CharField(max_length = 120) 
    body = models.TextField() 

Я думаю, что этот путь, расположение базы данных очень близка к концепции, имеющие содержание с общими атрибутами и переводимых полей.

Но тогда сложная часть остается СУХОЙ в вашем коде, или вы получите беспорядок шаблона каждый раз, когда вам нужно обрабатывать переводимый контент. К счастью, гибкость python оказала большую помощь.

Если ваш язык программирования и среда не позволяют подобные трюки (например, динамическое создание подклассов, python's metaclasses - какой-то крючок наследования и т. Д.), Я предполагаю, что этот вид макета базы данных будет скорее проклятием, чем благословение.

Итак, соблюдайте принцип YAGNI. Если вам нужны переводы внутри ваших моделей с меньшим количеством осложнений, я видел другие эффективные способы, которые хорошо до тех пор, пока вы можете позволить себе ограниченную гибкость и отсутствие концептуальной целостности этих альтернатив:

  • 1) использовать дополнительные столбцы для каждого переводимого столбца и каждого языка: title_en, title_fr, title_de, content_en, content_fr, content_de, ...
  • 2) сериализуйте несколько языков в одном столбце.
    Например: title = "| EN | Welcome | FR | Bienvenue | DE | Willkommen»
    Мне это не особенно нравится, но здесь важно то, что он прекрасно интегрируется в существующую среду, которая была именно так.
  • 3) Иногда связь между одним и тем же контентом на разных языках не обязательно должна быть строгой. Я думаю, что это относится к статьям в википедии - переводы - это просто гиперссылки, заданные авторами вручную. Как следствие, эти ссылки менее пригодны для использования программным обеспечением, но то, что здесь важно, просматривается пользователем.
1

Вот как это сделать на уровне базы данных.

Когда мне нужно было это сделать, я разбил каждую таблицу кода на две таблицы. Один из них содержит данные, не зависящие от культуры: внутренний идентификатор кода, сам код, если код был культурно-инвариантным, и, возможно, другие столбцы (например, категории сортировки/группировки). В другом - данные о конкретных культурах: описания, коды, специфичные для культуры, в случае необходимости и т. Д.

(Коды, предназначенные для конкретной культуры, являются гнездом шершни, не пинайте его, если вам это не нужно. Может быть немного сложно понять, что US и EU - это тот же код в разных но есть страны, где политически неприятно заставить франкоязычных пользователей использовать US в качестве аббревиатуры от États-Unis. Ну, a страна.)

Наличие таблицы кодирования с учетом культуры позволяет установить ограничения между ними и основные таблицы, которые ее используют. Построение культуры конкретных запросов довольно просто:

SELECT m.*, c.Code, ISNULL(s.Description, lf.Message) 
FROM MainTable m 
JOIN FooCodeData c ON m.CodeID = c.ID 
LEFT JOIN CultureSpecificFooCodeData s ON s.CodeID = c.ID AND s.Culture = @Culture 
JOIN LookupFailure lf ON lf.Culture = @Culture 

Обратите внимание, что если ваши коды культурной специфики, вы не должны даже присоединиться FooCodeData в этом запросе, выбирая s.Code вместо этого.

Обратите внимание также на одну неотъемлемую слабость этого подхода, как показано LEFT JOIN и ISNULL в этом запросе: вы не можете создать ограничение, гарантирующее, что для каждой комбинации кода/культуры существует определенная для конкретной культуры строка. Это то, что LookupFailure предназначено для: он получает специальное сообщение о культуре, которое указывает, что для кода не была введена запись кода для конкретной культуры.

Смежные вопросы