Лучше практиковаться для локализованных текстов в кроссплатформенных приложениях C ++? - PullRequest
23 голосов
/ 31 декабря 2008

В текущем стандарте C ++ (C ++ 03) слишком мало спецификаций по локализации текста, что усложняет жизнь разработчика C ++ при работе с локализованными текстами (безусловно, стандарт C ++ 0x поможет здесь позже. ).

Предполагается следующий сценарий (из реальных случаев разработки игр для PC-Mac):

  1. приложение, реагирующее (в режиме реального времени) : приложение должно минимизировать время отсутствия реакции на «не заметно», поэтому скорость выполнения важна.
  2. локализованные тексты : отображаемые тексты локализованы более чем на двух языках, потенциально больше - не ожидайте фиксированного количества языков, должны легко расширяться.
  3. язык, определенный во время выполнения : тексты не должны компилироваться в приложении (и не иметь одно приложение на язык), вы получаете информацию о выбранном языке при запуске приложения - что подразумевает некоторую загрузку текста.
  4. кроссплатформенный : приложение кодируется с учетом кроссплатформенности (Windows - Linux / Ubuntu - Mac / OSX), поэтому локализованная текстовая система также должна быть кроссплатформенной.
  5. автономное приложение : приложение предоставляет все необходимое для его запуска; он не будет использовать какую-либо библиотеку окружения или потребовать от пользователя установки чего-либо, кроме ОС (как, например, большинство игр).

Каковы лучшие практики для управления локализованными текстами на C ++ в такого рода приложениях?

Я посмотрел этот последний год, и единственное, в чем я уверен, это то, что вы должны использовать std::wstring или std::basic_string<ABigEnoughType> для манипулирования текстами в приложении. Я прекратил свои исследования, потому что я больше работал над проблемой «отображения текста» (в случае 3D в реальном времени), но я предполагаю, что есть некоторые лучшие практики для управления локализованными текстами в необработанном C ++ помимо этого и «использования Unicode» .

Итак, все лучшие практики, предложения и информация (кросс-платформенные, я думаю, это сложно) приветствуются!

Ответы [ 4 ]

17 голосов
/ 31 декабря 2008

В небольшой компании по производству видеоигр, Black Lantern Studios, я был ведущим разработчиком игры под названием Lionel Trains DS. Мы локализовали на английский, испанский, французский и немецкий языки. Мы знали все языки заранее, поэтому включение их во время компиляции было единственным вариантом. (Видите ли, они записаны на ПЗУ)

Я могу дать вам информацию о некоторых вещах, которые мы сделали. Наши строки были загружены в массив при запуске на основе выбора языка проигрывателя. Каждый отдельный язык вошел в отдельный файл со всеми строками в том же порядке. Строка 1 всегда была названием игры, строка 2 всегда первой опцией меню и так далее. Мы отключили массивы enum, так как индексирование integer очень быстро, а в играх скорость - это все. (Решение, связанное в одном из других ответов, использует string поисков, которых я бы старался избегать.) При отображении строк мы использовали функцию типа printf() для замены маркеров на значения. " Поезд 3 отправляется из города 1. "

Теперь о некоторых подводных камнях.

1) Между языками порядок фраз совершенно другой. « Поезд 3 отправляется из города 1. », переведенный на немецкий язык, и обратно получается « Из города 1, поезд 3 отправляется ». Если вы используете что-то вроде printf() и ваша строка « Поезд% d отправляется из города% d. », то в итоге немец скажет « Из города 3, поезд 1 отправляется.", что совершенно неправильно. Мы решили это, заставив перевод сохранить тот же порядок слов, но в итоге мы получили довольно разбитый немецкий. Если бы я сделал это снова, я бы написал функцию, которая принимает строку и массив значений, начинающийся с нуля, и помещает ее в нее. Тогда я бы использовал маркеры, такие как %0 и %1, в основном встраивая индекс массива в строку. Обновление: @Jonathan Leffler указал, что POSIX-совместимый printf() поддерживает использование маркеров типа %2$s, где часть 2$ указывает printf() заполнить этот маркер вторым дополнительным параметром. Это было бы очень удобно, если это достаточно быстро. Индивидуальное решение может быть еще быстрее, поэтому вам нужно убедиться и протестировать оба.

2) Языки сильно различаются по длине. То, что было 30 символов на английском языке, иногда доходило до 110 символов на немецком языке. Это означало, что это часто не подходило бы экранам, на которые мы его ставили. Вероятно, это меньше беспокоит игры для ПК / Mac, но если вы выполняете какую-либо работу, где текст должен помещаться в определенном поле, вам следует рассмотреть это. Чтобы решить эту проблему, мы удалили как можно больше прилагательных из нашего текста для других языков. Это сокращало предложение, но сохраняло смысл, хотя и теряло немного аромата. Позже я разработал приложение, которое мы могли бы использовать, которое содержало бы шрифт и размер поля и позволяло переводчикам вносить свои собственные изменения, чтобы текст помещался в поле. Не уверен, что они когда-либо реализовывали это. Вы можете также рассмотреть возможность прокрутки областей текста, если у вас есть эта проблема.

3) Что касается кроссплатформенности, мы написали довольно чистый C ++ для нашей системы локализации. Мы написали пользовательские двоичные файлы для загрузки и специальную программу для преобразования из CSV языкового текста в .h с enum и file to language map и .lang для каждого языка. Наиболее используемой платформой мы использовали шрифты и функцию printf(), но у вас будет что-то подходящее для любого места разработки, или вы можете написать свой собственный, если необходимо.

7 голосов
/ 20 июля 2015

Я категорически не согласен с принятым ответом. Во-первых, часть об использовании статического поиска в массиве для ускорения поиска текста просто показывает, что человек, выполняющий оптимизацию, очень неопытен - при расчете макета для указанного текста и его рендеринге используется 2-4 порядка больше времени, чем поиск хеша. Если кто-то хочет реализовать свою собственную языковую библиотеку, она никогда не должна основываться на статических массивах.

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

  1. Планирование времени для использования библиотеки локализации намного проще, чем планирование времени для написания библиотеки локализации. Библиотеки локализации существуют, они работают, и многие люди использовали их.

  2. Локализация сложна, поэтому вы все поймете неправильно. Каждый язык добавляет новую причуду, что означает, что всякий раз, когда вы добавляете новый язык в свою собственную доморощенную библиотеку локализации, вам нужно будет снова изменить код, чтобы учесть причуды. Знаете ли вы, что в некоторых языках имеется более 2 множественных форм, в зависимости от количества рассматриваемых предметов? Более 2 полов (более 10, даже)? Кроме того, форматы чисел и даты сильно различаются в разных языках.

  3. Когда ваше приложение станет успешным, вы захотите добавить поддержку большего количества языков. На языках никто в вашей команде не говорит свободно. Найм кого-то, чтобы написать перевод, будет значительно дешевле , если они уже знают инструменты, с которыми работают.

Очень известной и полной библиотекой локализации является GNU Gettext , которая использует GPL, и поэтому ее следует избегать для коммерческой работы. Вместо этого вы можете использовать библиотеку boost boost.locale , которая работает с файлами Gettext и может свободно использоваться и модифицироваться для коммерческих и некоммерческих проектов любого рода.

7 голосов
/ 31 декабря 2008

GNU Gettext делает все это.

0 голосов
/ 31 декабря 2008

Насколько я могу судить, в стандарте C ++ 0x не будет никаких дополнительных функций. Я подозреваю, что Комитет считает это вопросом для сторонних библиотек.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...