Unity3D
Comments 35
+1

2018 год на дворе, а люди по-прежнему занимаются копи-пастингом переводов из/в CSV и Excel.


Существуют же gettext а также миллиард программ и сервисов для перевода файлов gettext. Строки автоматически собираются из исходного кода (никто не должен вручную проверять и вносить правки при изменении кода/ресурсов), переводчики сразу видят строки, которые надо перевести, переводы валидируются (например, чтобы не возникало ошибок из-за опечаток в названиях placeholder'ов, таких как Сишные %s, %d), после перевода все переведенные строки автоматически доступны приложению.


Для перевод po файлов существует просто прорва онлайн сервисов, GUI программ, self-hosted сервисов (я, например, использую сейчас Weblate).


Как при всем таком многообразии инструментов, которые значительно автоматизируют и облегчают процесс, рекомендовать до сих пор CSV и Excel?.. Неужели Unity не поддерживает ничего лучше?

0

Наверное в играх строк немного. Просто я работал в проектах, где локализация производится через Excel. Это просто средневековье какое-то. Людям приходится вручную заниматься монотонным копированием строк туда-сюда, в котором очень легко ошибиться. Неблагодарная тяжелая работа, которая элементарно автоматизируется, и решения для автоматизации придуманы очень давно (GNU gettext появился в 1995 году).

0
Стоит также учесть специфику разработки. Если вы начинающий инди-разработчик, который пришел к Unity именно из-за низкого порога входа и C#, то вряд ли вам нужно все то, о чем вы рассказываете. Мне, например, определенно хватает и CSV.
0

Так в gettext ничего сложного нет. Строки помечаются в исходном тесте (чаще всего используется синтаксис _("строка")). Утилиты gettext сканируют исходный текст, находят отмеченные строки и записывают в .po файл.


.po файл можно переводить вручную, как тот же csv, можно преобразовать в csv, можно редактировать GUI редактором (существует множество), можно отдать на аутсорс, можно загрузить в онлайн-сервис наподобие OneSky, можно установить свой веб-сервис, такой как Weblate (у Weblate есть еще не менее 5 аналогов).


Затем полученный переведенный файл распространяется вместе с продуктом, и во всех местах вызов gettext (_("строка")) подставляет переведенный текст. Все, кроме собственно перевода, полностью автоматизировано. Перевод, в зависимости от выбранного решения, тоже можно полностью или частично автоматизировать.


Один раз настраивается, затем все происходит автоматически. Один раз попробовав, уже не захочется ничего другого.


Ну а CSV я тоже работал, конечно. Когда строк больше сотни, тут уже на каждой итерации требуется значительное количество ручного труда.

0
Обычно фиксированных строк в геймдеве мало и они пробиваются не в коде, а в метаданных сцены юнити (можно принудительно заставить сериализовать эти данные в YAML, а потом долго и мучительно выковыривать их, но...), большая же часть собирается динамически и практически никогда не забивается строками на «original»-языке в коде, а сразу едет как токен в локализацию. Т.е сканировать как бы и нечего.
0
Тут фишка в том, что CSV можно использовать не только как данные локализации, но и как таблицы для баланса игровой механики — неплохая замена ScriptableObject и не завязано на юнити и ее апдейты, которые всегда-что-то ломают.
0
Ох, внешние параметры для игры — это отдельная тема. Но Unity работают над этим, может что-то и выйдет в ближайшее время.
0
Ну вот простой пример.
Задаются ограничители данных, списки выбора и т.п. Первая строка — имена JSON-полей, вторая строка — символы для экранирования (по сути определяют тип данных). От дизайнера защищены как 2 первые строки, так и первый столбец. Это все дампится через CSV, потом автоматически конвертится в JSON и складывается в Resources. В рантайме уже происходит загрузка и маппинг прямо на внутренние классы через JsonUtility или что-то иное.
0
Я раньше делал еще проще — хранил сериализованный конфиг игры. А игра еще и умела его подгружать в процессе, чтобы билды новые не делать из-за изменения баланса. Но это уже совсем другая история)
0
Ну тут смысл такой же — дизайнеру даже не нужно иметь установленную юнити, можно прикрутить подгрузку / парсинг в рантайме. Ну и совместное редактирование с историей правок и возможностью применения формул для балансировки.
0
А мы подняли сервер на гуглокоде, который через api docs по схожему принципу вытаскивает данные и просто отдает JSON в Unity, где его из промежуточного формата (если требуется) превращают в ScriptableObject.
0
Тоже вариант, хотя и более тяжелый по реализации и поддержке. Основной посыл был — избавиться от необходимости крутить циферки в юнити и рисования кастомных инспекторов. Ну и если потребуется — это все можно провернуть на лету, немного подхачив код, тогда вообще можно будет подсасывать данные прямо в билде. Со SO такое невозможно.
0
Реализации да, поддержка — нет. Один раз настроил и работает. У каждой таблицы добавляется еще одна вкладка Schema — которая описывает формат JSON который нужно сформировать для Unity.
Но там без связей. И вот связи приходится на клиенте восстанавливать. Инспектор кастомный делать не нужно, кнопку скачивания можно вынести в меню.
То что надо на лету подсасывать, это уже должно быть из нормальной базы данных с нормальным бекэндом. Api гугла медленное, чтобы не злоупотребляли. Для ГД еще можно сделать, для игроков — нет. Поэтому скрипты для работы я в Editor засунул.
0
Я про поддержку апи гугля — оно может меняться и за этим нужно следить. А стаскивание данных по прямому урлу работает с момента существования гуглодоков. Работает довольно быстро и без временного лага до 30 минут, как в в штатной публикации в веб. Понятно, что это не для продакшна, но для быстрого тестирования у дизайнеров / внутренних тестировщиков с изменением циферок на лету — вполне сойдет.
0
За год не сталкивался с такими изменениями. Поживем увидим :). Главное чтобы данные не пропали, а как их достать — всегда можно придумать.
0
Как обрабатываются многострочные ячейки? Имеется ввиду строка, в которой прямо внутри набиты переводы строк (не через пару символов "\n"). Такие csv тоже являются, как ни странно, валидными, пусть и строка таблицы разбита в файле на несколько подстрок.
0
У меня не было проблем с ними. Ведь служебные символы так и переезжают в локализацию, где их рендерит компонент Text.
0
Это проблема парсинга таких CSV, это специальный кейс, который нужно обрабатывать — это делается?
0
Да, только кавычки остаются. Но код открытый, простой и будет только рад допиливанию)
0
Кстати, переносы строк экранируются двойными кавычками при скачивании CSV. Так что проблем не будет. Главное, чтобы парсер корректно это прочитал. Мой парсер такое обрабатывает, но оставляет кавычки. Исправлю как нибудь)
0
Т.е есть уже один известный баг. :)
А вообще, тема довольно старая и уже деланная-переделанная много раз, даже на хабре были ссылки.
*) Локализатор: поддерживает загрузку фиксированных данных, а так же «динамических» (можно подгружать / выгружать с возможностью переопределения ключей).
*) Локализация компонента Text uGui: поддерживает автоматическое обновление при смене языка в локализаторе.
*) Локализация компонента Image uGui: поддерживает автоматическое обновление при смене языка в локализаторе.
*) Скачивание нескольких CSV-файлов с сохранением url / путей: поддерживает конвертацию в JSON-array / JSON-dict.
*) Скачивание нескольких CSV-файлов в виде отдельного репозитория без зависимостей.
0
Видел и статьи, и гитхабы. Но хочется же ничего не делать, чтобы оп — и готово. Пришлось делать самому.
0
А как решается проблема, когда нужно изменение самого UI? Например, на разных языках размер элемента должен быть разным.
0
Ну есть же всякие ContentSizeFitter и HorizontalLayoutGroup. Хотя я обычно просто устанавливаю динамичный размер текста, чтобы он вписывался в размер элемента.
0
Если вы используете Best Fit для текстовых компонентов, то он плохо сказывается на производительности, особенно если у вас есть какие-то прокручиваемые списки с кучей текстов
-2
Я человек простой. Если пользователи жалуются на тормоза — я буду искать причину. В остальное время я нацелен на конечный результат. В процессе работы меня мало интересуют нюансы реализации локализации и специфика работы uGUI. Главное, чтобы заработало побыстрее. Все эти паттерны, рефакторинги и оптимизация — кому они нужны, если проект не зашел? Да, есть и такие, кто считает, что в паттернах и всяких крутых вещах, вроде gettext, и есть суть разработки. Их право.
0
Те которые жалуются, это лишь малая, большинство недовольных просто закрывают апп и удаляют. И вы даже не узнаете причину.
0
Есть и другая точка зрения. Если приложение или игра того стоит — то буду жаловаться. А если нет, то оптимизация не поможет.

Кроме того, аналитику и Performance Reporting никто не отменял.
0
CSV (Comma Separated Values). Это текстовый файл, в котором все ячейки разделены разделителем — либо запятой (","), либо точкой с запятой (";")


Наличие точки или точки с запятой в самом тексте в одной из ячеек не порушит структуру файла?
Only those users with full accounts are able to leave comments., please.