Локализация Android приложения средствами Google Sheets

Добрый день!

В данной статье хотелось бы поделиться своим небольшим опытом использования Google Таблиц при локализации Android приложения. Изначально требовалось перевести разрабатываемое приложение только на язык заказчика, т.е. норвежский. В это время в IntelliJ Idea не существовало Translations Editor'a, а Android Studio готовилось к выходу из беты.

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

TL;DR готовый документ. Чтобы получить файлы strings.xml, жмем Export Files -> Export sheets to strings.xml. Приложение Google Drive, которое должно быть установлено на вашей машине, скачает результат.

В самом начале мы использовали простой Excel документ для перевода и email пинг понг с переводчиком для общения с ним. После ручного переноса ~100 строк из strings.xml в таблицу желание продолжать это постыдное занятие отпало. Был реализован импорт из xml в таблицу средствами Excel. В дальнейшем данный документ обрастал логикой: разного рода условное форматирование для визуализации вновь добавленных строк, поддержка ситуации, когда ключ от строки был переименован.

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

В итоге был получен втык от заказчика, а также новое требование: никакой сложной логики в таблице, только 4 колонки — ключ, английский исходник, норвежский, шведский и датский переводы. Чтобы избежать проблем со множеством копий документа от каждого из переводчиков, я уговорил заказчика использовать Google Sheets. Я уже не собирался экспортировать переводы в strings.xml каким-либо ручным способом — с лихвой наелся высматриванием несовпадений в строках после того злополучного слияния разных копий перевода, когда от таращения в монитор выступал пот на лбу. Затем оказалось, что для Google сервисов можно очень просто писать расширения на JS подобном языке — Google Script.

Естественно, я искал готовые сервисы, решающие данную проблему. Первые 3 ссылки в гугле и ответ на SO не дали удовлетворительных результатов. Кстати, к моменту перезда на Google Sheets вышла новая версия Idea, где появился Translations Editor, это немного упростило жизнь.

Итак, была создана таблица в документах гугла c 5 колонками — ключ, английский, норвежский, шведский, датский и комментарии, а также розданы права доступа. Чтобы поместить данные в таблицу из проекта, нужно выделить все в Translation Editor'e и вставить в любой редактор таблиц, удалить лишние столбцы (Untranslatable — мы не используем его) и вставить результат в гугловский документ. Необходимо также упомянуть, что наш проект состоит из нескольких модулей со своими переводами, поэтому в документе имеется 2 вкладки, а описанные операции надо выполнить по разу для каждого проекта.

В итоге получается таблица со строками для перевода, которую переводчики без труда могут вместе редактировать. Когда перевод закончен, необходимо перенести результат назад к себе в проект. Я начал думать, как бы мне получить все и сразу. Максимальные усилия, на которые я готов был пойти, — это 1 копирование. Единственное решение, которое мне пришло на ум — это экспортировать результаты в Google Drive, откуда десктопным приложением они подтянутся мне на ПК. Если предварительно была создана правильная иерархия папок, то я смогу скопировать и перезаписать файлы strings.xml в 1 действие. Тут без написания небольшого скрипта не обойтись.

Нажимаем Инструменты->Редактор Скриптов и попадаем в почти полноценную IDE с автодополнением и дебагом прямо в браузере! Также создался небольшой кусочек кода, который создает дополнительное меню вы UI таблиц гугла. Нажатие на этот элемент и будет входной точкой.

function onOpen() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var entries = [{
    name : "Export Sheets To strings.xml",
    functionName : "readAndExport"
  }];
  spreadsheet.addMenu("Export Files", entries);
};


Далее нехитрый код проходит по листам(вкладкам), считывает заголовки столбцов, составляет xml строку из значений в ячейках и пишет ее в файл strings.xml на вашем гугл диске в директорию trunk/[sheet_name]/res/values-[column_name]/strings.xml. Сам исходник можно посмотреть непосредственно в представленном файле. Из необычного можно упомянуть, что в гугл драйве имя директории или файла не является уникальным, т.е. можно создать 2 файла или директории с одинаковым именем. Чтобы все правильно работало, нужно использовать примерно такой код:
function getOrCreate(root, name) {
  var iterator = root.getFoldersByName(name);
  if(iterator.hasNext()) {
    return iterator.next();
  } else {
    return root.createFolder(name);
  }
}


Вывод


Google Apps обладают поистине простым и в то же время мощным API. Еще одним достоинством является тот факт, что сразу из коробки имеется доступ к API любого приложения Google: календарь, диск, почта и т.д. Мне в кратчайшие сроки удалось создать простой и удобный инструмент для локализации нашего приложения. Конечно, в нем еще есть места, которые хотелось бы улучшить, однако, я избавился от самой главной проблемы: копирования и редактирования множества файлов с одинаковой структурой и именами. Это неизбежно вело к ошибкам, вызванных невнимательностью.

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 10

    0
    Для первого шага неплохо, но есть пара вопросов.

    Как у вас решается проблема обновлений? Скажем, из 200 значений для исходного языка к следующей версии разработчик поменял 20 (не меняя ключей), добавил 10 и удалил 5.

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

    Не сочтите за рекламу, но для более серьёзной работы (~10000 строк, ежедневные обновления некоторых фрагментов) мы использовали платный сервис Crowdin, вполне прозрачно решающий практически все проблемы, возникающие в процессе локализации. Для разработчиков всё получалось просто: push/commit в одну из систем контроля версий, скрипт синхронизации сам вычитывает и заливает в сервис все изменившиеся файлы, а после окончания перевода автоматически коммитит результат обратно.

    Всё зависит от многих факторов, и ваш способ вполне подходит, если платформа одна, проект небольшой и переводчикам не требуется Translation Memory. Но я бы не рекомендовал его к использованию в непрерывно разрабатываемых проектах, ресурсные файлы которых превышают 100-200 строк.
      0
      Проблема обновлений решается просто — целиком перезаписываем документ данными из IDE, переводим, экспортируем, перезатираем файлы в проекте, пуш, GOTO 0.

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

      Существует несколько онлайн тулов, но они все платные, что влечет за собой возню с бюрократией (самое удивительное, что этой возни нет при единоразовой покупке по R#, dotCover), но там где подписка, начинаются проблема + нужно было бы пинать администратора, администрирующего наш git/gerrit. Заказчик считает, что время разработчика дешевле этой возни.

      10000 тысяч строк — это уже монстр какой-то. В нашем проекте их ~300.
        0
        А я и не говорил, что 10000 строк — это один проект. Это весь портфель проектов довольно крупной компании, выходящей на международный рынок. Но суть не меняется.

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

        1. Скриптом парсим нужные файлы по заданному шаблону в табличку (да хоть CSV, если его умеет Гугл). Как раз в этот скрипт можно и заложить парсинг контекста (в Android strings.xml это XML-комментарий, непосредственно стоящий перед нодой строки).
        2. Если в Google Drive уже лежит подобная табличка, для каждой строчки старой таблички проверяем, если в новой таблице есть такой же ключ с таким же значением на исходном языке — заменяем новую строку со всеми переводами старой строкой, т.к. всё уже переведено.
        3. Если в новом файле осталось что-то непереведённое, заменяем его и триггерим какое-то событие «пнуть переводчиков» (SMS, Email, Jabber…).
        4. Перепинываем ссылку на документ между переводчиками и пруфридерами до готовности, после чего выгружаем и сохраняем себе, куда надо.
        5. ????
        6. PROFIT!
        0
        Позвольте узнать, как решается проблема с контекстом в сервисе Crowdin?
        0
        Я джва года ждал такой скрипт!
        Сам делаю в гугл таблицах словари, из них выгружаю в Эксель, в Экселе собираю инсерты для БД.
          0
          Моего знакомого нет на хабре, но статья его заинтересовала и он попросил меня задать вопрос вам. Буду рад если откликнитесь

          «Наша фирма разрабатывает приложения сразу на 3 платформы: Android, WP и iOS. Собственно интересует вопрос, как лучше организовать локализацию сразу на 3 платформы? По поводу Android и WP особых вопросов не возникает, все делается также как и было описано в этой статье, только скрипт на питоне. А вот с iOS есть проблемы, так как локализация там кардинально отличается.

          На данный момент мы решили сделать так: К локализованной строке добавляется строковый комментарий с именем ID, питоновский скрипт ищет ресурс под этим комментарием и локализует его.
          Недостатки: Для генерации файлов локализации нужны сгенерированные .strings для всех языков, Xcode пытается оптимизировать ресурсы и склеивает 2 одинаковых в один, в результате чего теряется возможность создавать 2 разных перевода в зависимости от контекста.

          Я предлагал решить эту проблему путем подстановки ID вместо строки, тогда бы получился файл вот с такими строками:
          »string_res_1" = «Localized string 1»;
          «string_res_2» = «Localized string 2»;
          и так далее…
          Но iOS программист отказался так делать, сославшись на то, что если мы забудем локализовать какую либо строку, пользователь может увидеть невнятный код вместо человеческого сообщения на английском языке, да и в сторибоард с кодами экран выглядит не так как должен быть."
            0
            «Со сторибоард, кстати, отдельная тема, так как нет возможности повлиять на генерацию комментариев и ID ресурсов. В итоге все переводится в коде 0_о. Тесть получаются ссылки на UILabel и в коде им ставится локализованный текст.»
              0
              Это вы мне или Archon? Если мне, то я тут ничем не могу помочь, нет опыта ни iOS, ни WP.
                0
                Нет, это автору. Комментарий же рутовый
                  0
                  Мало ли, может промахнулись :)

          Only users with full accounts can post comments. Log in, please.