убеждённый сторонник второго варианта.
код пишут чтобы читать.
строковые литералы - это важнейший источник информации для понимания кода при беглом просмотре. комментарии в коде могут быть, а могут отсутствовать. наименование классов-методов-функций-переменных-констант может быть по смыслу, а может и не быть. но код, который пишет пользователю что-то, так или иначе с этим чем-то связан.
любое разбирательство в малознакомой или хорошо забытой кодовой базе начинается с локализации проблемы с точки зрения пользователя (в подавляющем большинстве случаев, это значит в интерфейсе), а потом уже попыток понять "чем он это сказал". и простой поиск текста по исходникам во втором варианте позволяет сразу просмотреть списком все места где этот текст встречается, а в первом варианте вынуждает ещё искать по одному вхождения каждого из ключей.
особенно отвратительно, когда первым выриантом локализуется форматная строка от какого-нить принтф: какие-то параметры передаются, а как трактуются - не выяснить без рытья по ресурсам.
сама необходимость придумывать осмысленные ключи для каждой строчки в первом варианте - это то ещё развлечение. одно из двух признанных сложнейших дел во всём программизме (классика: именование вещей и инвалидация кэша) внезапно увеличивается на количество всех строчек в софте.
вот что у первого варианта лучше, это поддержка со стороны инструментария. всякие ide табличками ресурсы на разных языках показывают, существуют удобные онлайновые средства для колективного перевода, и так далее.
однако, на практике это всё не работает, потому что перевод софта - это процесс с деятельным участием специалистов заказчика (они же всегда лучше знают как правильнее, даже если сами ни в зуб ногой), а их юридическому отделу ide не подсунешь, и согласовывать их шеф будет по конторскому документообороту, в крайнем случае распечатку. в общем, в реальных проектах между конторами гоняется файлик со строчками софта в ёкселе. который конвертируется в ресурсы и обратно какой-нить самопальной тулзой, а потом долго, с матом, вручную мержится с ресурсами в софте, потому что недопереводчики очень любят как попало править и то, что им поручили, и что-нибудь ещё, на остальных языках (типа, "в той формулировке красиво не переводится, лучше пусть так будет").
и это приводит к основному минусу второго подхода: когда правится текст на основном языке, надо будет ещё поправить все вхождения этой строки по всему софту. впрочем, стандартные инженерные практики (dry, обобщение повторно используемого кода) успешно препятствуют слишком уж большому количеству повторений одного и того же в разных местах.
насчёт разных переводов одной фразы - да, такое бывает, но реально очень редко. настолько редко, что какой-нибудь костыль с добавленным пробелом и комментарием зачем он там нужен, субъективно не кажется чем-то, что следовало бы вместо этого обрабатывать на уровне механизма. я буквально пару-тройку раз могу вспомнить за 20 с лишним лет написания софта для местного рынка. а я в казахстане живу, тут всё на нескольких языках и это закреплено законодательно.