Вчера я закончил на том, что сажусь за экран покупки. И что придумать цену мне страшнее, чем написать.
Сегодня история вообще не про цену.
Она про то, как я надумал делать переводы.
Но началось всё, как и обещал, с оплаты.
💳 Виртуальные деньги
В первый день я писал, что в поезде не поднимешь окружение и не погоняешь приложение.
Сегодня я сижу в вагоне и покупаю собственное приложение. Снова и снова.
Деньги, конечно, ненастоящие. Xcode умеет притворяться магазином: описываешь товар в одном файле, и покупка проходит целиком — окно, подтверждение, ответ магазина. Без сети и без единого настоящего доллара.
С платформой Apple напрямую я дела почти не имел. Поэтому было по-настоящему интересно, как это будет выглядеть.
Выглядит классно. Всё понятно и грамотно, и с Xcode я заодно познакомился чуть ближе.
Потестировал. Поделал виртуальных оплат. Поснимал их обратно. Погонял туда-сюда — посмотрел, как всё работает в обе стороны.
Заодно добавил счётчик, который намекает, что лимит подходит к концу. Появляется он, только когда осталось восемь, — не раньше.
Ничего сверхъестественного. Развлечение минут на тридцать.
А вчерашний страх никуда не делся.
Сама цена висит на лендинге с первого дня: $9.99, один раз. Страшно не число. Страшно — сработает ли оно.
Не слишком ли дорого? Не слишком ли дёшево? Где баланс между тем, сколько отдать бесплатно, и тем, за что людям будет приемлемо заплатить?
Ответа у меня нет. Есть только другая сторона.
Я тут хороший парень.
Не лезу в карман подпиской.
Не прошу оплату сразу.
Даю разумный лимит, чтобы попробовать.
Не жадничаю с разными платформами.
В общем, топ за свои деньги.
И про лимит. На том же лендинге с первого дня висит ещё одно число. Я тогда просил его запомнить и обещал к нему вернуться.
Вот оно.
Двадцать четыре сниппета бесплатно и навсегда. С сегодняшнего дня это число живёт не только на странице, но и в коде.
И пара деталей, которые мне нравятся больше, чем следовало бы.
Предел стоит не на кнопке, а там, где сниппет создаётся. Иначе любой другой путь его бы обходил.
Сниппеты при этом не читаются, а только пересчитываются. Содержимое сейфа остаётся зашифрованным, наружу выходит одно число.
Счётчик, который не читает то, что считает.
И отказ ничего не стирает. Раньше человек набрал бы строку, нажал — и вместо сниппета получил окно про покупку, а строку потерял. Теперь создание честно отвечает, сохранило оно или нет, и то, что не поместилось, остаётся в поле.
👹 iddqd
С оплатой я закончил где-то между Ниагарой и Гамильтоном.
А по Гамильтону ехал уже с другим в голове. Дальше жопу потянуло на развлечения.
Ну нельзя же сделать приложение без пасхалок.
А что может быть лучше, чем вспомнить что-нибудь древнее. Настолько древнее, как Doom.
Насколько я догадываюсь, такие коды часто ставят не ради веселья. Через них проверяют пути распространения: кто откуда пришёл, какой код ввёл, что сработало.
У меня такой телеметрии нет.
С самого начала я заложил в приложение правило: у нас нет доступа к данным на стороне пользователя. Ни бэкенда, ни аналитики.
Я просто сильно не люблю такие приколы.
Когда ты не знаешь, до какой грани твои данные ещё твои, а откуда начинается жёсткий абьюз.
Когда кто-то в любой момент может поменять политику сбора информации, просто прислав апдейт на почту.
Мне такое говно не нравится.
Поэтому здесь пасхалка — просто развлекуха. Ну и вам, читателям, будет занятно.
И в этом свете я заодно переосмыслил лимиты.
Двадцать четыре остаются. Но если ввести чит-код из Doom — станет на десять больше.
Ну или меньше. Читы там были разные.
Как зайдёт — расскажете)
Сделано, впрочем, всерьёз.
Десять не прибавляются, а выставляются. Вводи код хоть сто раз — сверху будет ровно десять, не больше. И бонус записан в настройках, так что переживает перезапуск.
А если ввести код после покупки, давать уже нечего. Тогда приложение просто отвечает: «God mode у тебя куплен. Молнии — за счёт заведения».
Потому что за курсором ещё и тянутся молнии.
Пользы от них ноль. Но и они сделаны аккуратно. Рождаются от слежения за мышью, а не от прозрачного слоя поверх всего — иначе такой слой перехватывал бы нажатия у каждого блока под ним. А рисование засыпает само, когда не осталось ни одной молнии, так что неподвижный курсор не стоит ничего.
Я потратил время на то, чтобы бесполезная вещь была сделана правильно.
А вот как вся эта пасхалка стыкуется с остальным приложением — не вникал. Идея была самоценной.
Тоже минут на тридцать.
🎮 Полчаса Ведьмака
А в поезде мне ехать два часа.
Так что сегодня я себе таки разрешил потратить полчаса на Ведьмака.
Вчера вышел ремастер. Тот самый, который в понедельник лежал на свиче и ждал волшебной даты.
И знаете…
Мой родной язык — не английский.
И как же прикольно поиграть в игрулину на своём языке.
Это как удобные тапочки. Именно твои, и на твоём языке.
Подумал я об этом уже на подъезде к Торонто.
И решил прикинуть: а сколько времени это займёт у меня?
🌍 Двенадцать языков до офиса
Как выяснилось — да не то чтобы сильно долго.
Английский был с самого начала. Добавилось двенадцать: русский, украинский, немецкий, французский, испанский, португальский, итальянский, японский, китайский, корейский, бенгальский и хинди.
Язык берётся системный. Включать ничего не надо.
Переводит, конечно, не я — переводит ИИ. Проблема была в другом: проверить всё приложение на тексты, которые остались непереведёнными.
В 2026 году это не так трудно, как кажется. Просто берёшь и пробуешь.
Это правда больше тест на внимательность, чем на знание.
Например, список строк, которые надо перевести, нельзя собрать поиском по файлам. Строки внутри условий и строки с подставленными числами поиск не находит — их пришлось брать из того, что видит сам компилятор.
А часть надписей молча осталась бы английской. Есть два способа вывести текст, выглядят они одинаково, и один из них не переводит. Заголовки разделов, строки настроек, первое знакомство с приложением, подписи у цветовых ползунков — всё вокруг перевелось бы, а это осталось.
И тут помогают сами языки.
Хинди, бенгальский, японский — идеальная среда, чтобы увидеть, где какое слово или уведомление не переведено. Английское слово посреди деванагари не спрячется.
Три языка из двенадцати я знаю сам, их проверю сам. Ещё поспрашивал коллег: нашлись знатоки хинди, бенгальского, корейского и японского. Так что есть с кем это дело проверить.
Имя доски решается в момент, когда её создали. Доска, названная на русском Mac'е, остаётся с русским именем, даже если систему потом переключат.
И главное.
Шутки в приложении не переведены. Они написаны заново, каждая под свой язык.
Помните «ну или меньше»? У каждого языка на этот случай своя пословица про наказанную жадность. Не одна пословица в двенадцати вариантах, а двенадцать разных.
А «god mode» в пяти языках уступил место местному слову. В хинди и бенгальском это дар. В японском, китайском и корейском — режим неуязвимости. Английское геймерское словечко там лежит инородным телом, а шутка, которую надо объяснять, — уже не шутка.
Ну и настройки пришлось расширить на шестьдесят пунктов. Ползунок занимал сто сорок, на подпись оставалось около ста двадцати, и языки подлиннее в них не влезали.
Двенадцать языков — это не двенадцать файлов. Это двенадцать разных представлений о том, сколько места занимает слово.
Когда я выходил из поезда, я был тем самым странным парнем с открытым ноутбуком в руках.
Но ещё до того, как я зашёл в офис, у меня было двенадцать языков.
Да, их ещё надо прочитать и проверить. Никто не идеален.
Но это то, что может хорошо помочь с продвижением. И вот почему.
Англоязычный рынок самый прибыльный. Но вместе с этим и самый конкурентный.
Если делать из моего продукта то, что будет продаваться, то лучше делать охват побольше.
🔌 Engineer honesty moment
Полчаса развлечений у меня сегодня ушло на деньги и полчаса на пасхалку. А вот три вещи из того же дня, которые развлечением не были.
Первая — гонка. После того как покупка завершена, у системы можно спросить, что человеку теперь принадлежит. Я спрашивал сразу.
Слишком сразу. Покупка уже прошла, а ответ ещё говорит «ничего не куплено».
Теперь право даётся из самой подписанной покупки, а переспрашивать систему имеет смысл в одном случае — когда покупку отозвали.
Вторая — возврат. И вот тут смешно. До сегодняшнего дня отозвать покупку было нельзя вообще.
Флаг «куплено» умел говорить только «да» и «нет». А «ещё не спрашивали» и «спросили, покупки нет» оба выглядели как «нет». Поэтому, если человек вернул деньги, приложение этого просто не замечало и оставалось разблокированным навсегда.
Теперь у флага три состояния. И он — кэш, а не решение. Решает всегда магазин.
Разница между кэшем и решением — примерно всё, что нужно знать про деньги в приложении.
Третья — смена уровня приватности. У доски их три: обычная, защищённая отпечатком, сейф с паролем.
И было странно, что их можно вот так просто переключать.
Сменить уровень мог кто угодно, у кого перед носом открытое приложение. Доска уже разблокирована — значит свой, значит можно.
Нет.
Разблокировано — это не доказательство. Это значит, что кто-то доказал право один раз, а потом отошёл за кофе.
Незнакомый человек у незапертого Mac'а мог перевести вашу доску в сейф со своим паролем. И запереть вас снаружи вашей же функцией.
Теперь смена уровня требует доказать тот уровень, на котором доска стоит сейчас, даже если она открыта. А новый уровень включается сразу: пароль проверяется в момент, когда его придумали, а не в тот момент, когда его забыли.
Закрыть-то закрыл. Но весь этот блок ощущается очень большой штукой, которую ещё тестировать и тестировать.
💬 Вопрос
О цене я думаю с тех пор, когда не было ещё ни строчки кода. Языки сделал по дороге в офис.
Сколько вы готовы один раз заплатить за маленькую штуку, которой пользуетесь каждый день? И сколько бесплатного вам нужно, чтобы это понять?
Мой ответ пока такой: двадцать четыре сниппета, чтобы по-настоящему попробовать, и дальше $9.99 — один раз и навсегда. Сработает ли — не знаю.
Расскажите, как у вас 👇
Двенадцать языков у меня есть. Прочитанных — пока ни одного.
Завтра хочу пройтись по всему приложению глазами того, кто будет проверять его перед магазином. И подозреваю, мой чит-код ему не понравится 😉