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

StackOverflow https://stackoverflow.com/questions/403747

  •  03-07-2019
  •  | 
  •  

Вопрос

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

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

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

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

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

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

Это было полезно?

Решение

В небольшой компании по производству видеоигр 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, по сути, встраивая индекс массива в строку. Обновить:@Джонатан Леффлер указал, что POSIX-совместимый printf() поддерживает использование %2$s введите маркеры, где 2$ часть инструктирует printf() чтобы заполнить этот маркер вторым дополнительным параметром.Это было бы весьма удобно, при условии, что это будет достаточно быстро.Пользовательское решение все равно может быть быстрее, поэтому вы захотите убедиться и протестировать оба варианта.

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

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

Другие советы

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top