Создание меню на BASH — задача сама по себе не сложная: "case тебе в руки и echo в спину". Решая её в очередной раз, мне захотелось добавить возможность отображать текст на других языках. Осталось решить, как сделать сам процесс локализации меню более удобным. Если оно большое, то решение "в лоб" превратит его в громоздкую копипасту. Здесь я хотел бы поделиться тем, как решил эту проблему для себя. Надеюсь, для кого то это будет небезынтересным.  Чтобы статья не вылилась в скучную простыню с излишком кода, решил разбить её на две части. В первой рассмотрим создание и добавление дополнительных языков. Во второй — создание многоуровнего меню и сохранение настроек Я вполне понимаю и принимаю, что существуют и другие языки программирования. Как когда-то кто-то сказал здесь на Хабре — если при написании скрипта на BASH возникает необходимость хоть в одной функции, то лучше взять нормальный язык. Я с этим согласен, но иногда, как говорится, хочется, потому что хочется. Мне не хотелось бы разбивать скрипт на несколько частей и хранить локализацию в отдельных файлах. Скрипт тем и удобен, что его проще использовать одним файлом. Поэтому тексты будем хранить в массивах.  Реализация будет состоять из: Теперь рассмотрим подробнее Зададим язык, добавив короткий буквенный код языка (ru, en), для начала английский: Добавим массивы слов и предложений (по количеству языков): Создадим косвенную ссылку и сформируем из неё новый массив в переменной lng: То есть здесь для переменной lng создаётся значение, состоящее из части имени массива со словами и кода заданного языка из переменной langset. Далее создаётся массив, который при langset=en будет равен language_en, а при langset=ru будет равен language_ru.
Если языков будет много, то такой подход позволит избавиться от многочисленных if-elif или case. Чтобы изменить язык, достаточно будет добавить массив с переводом и установить язык в переменной langset. Запустим всё это в консоли: Таким образом, указывая в начале скрипта двухбуквенный код языка, можно задавать вывод одних и тех же слов или фраз на разных языках.  А теперь попробуем создать скрипт.
Для примера я взял меню управления командами Git через CLI (command line interface). Это немного надуманно, но хорошо подходит для примера, так как в Git много команд и как раз можно построить единое по своей задаче меню с множеством параметров. Для начала задаем язык и массив с пунктами меню как это уже делали выше. Ради удобства, я разделил массив на две части: первая — это непосредственно меню, вторая — информационные сообщения и приглашения командной строки, которые необходимо будет вывести по ходу работы.  Пройдемся по массивам и создадим новые для lng и msg, которые и будут использоваться: Чтобы при необходимости иметь возможность применять языковые настройки (это пригодится в следующей статье), заключим всё в функцию и тут же вызовем её. Небольшое отступление: я уверен, почти всем встречались наполовину переведённые приложения. Особенно этим грешат кастомные прошивки для телефонов. Мне никогда это не нравилось, но в данном случае я всё же решил предусмотреть такую возможность неполного перевода. Это позволит при добавлении нового языка не дублировать все элементы массива, а добавить только те, которые пользователю хотелось бы перевести. Для этого в цикле сравним созданный массив с англоязычным (английский считаем языком по умолчанию): если записи не существует (либо элемент массива пуст), дополним англоязычным вариантом. Теперь, когда с языками разобрались, приступим к построению меню. Тут всё стандартно: бесконечный цикл, внутри него цикл для вывода элементов на экран и выбор вариантов через case. Формируем массив для вывода на экран. Только те пункты, которые нам нужны: Здесь делаем индексацию с 1, чтобы выводить индекс как соответствующий пункт меню. Добавляем шапку, пробегаемся по индексам через ${!menu0[@]} и выводим на экран: Далее предложим пользователю выбрать необходимый пункт. Будем ожидать нажатие цифровой клавиши через read -s -n1 -p. Где -s — не отображать введённые данные (чаще используется для ввода паролей). Мы же потом сами отобразим введеный текст в более удобном формате. -p — строка приглашения для вывода подсказки. -n1 — параметр, считывающий число симмволов ввода. Здесь мы заранее знаем, что пунктов меню будет не более 9 (то есть числа из одной цифры), поэтому при нажатии одного любого символа программа продолжит работу дальше. Не надо будет нажимать Enter для ввода. Немного непривычно, поэтому можно убрать. Ну и заключительный оператор выбора case с обработкой введенного значения: Здесь case сделан упрощенным, только для примера. В следующей статье я буду использовать его в более универсальном варианте. Это первая статья из двух. В следующей рассмотрим создание многоуровнего меню, разукрасим вывод (как же без этого), а также попробуем сохранить настройки, то есть задать код языка прямо из меню, не открывая Shell-скрипт в текстовом редакторе. Спасибо, что дочитали до конца. Надеюсь, было не скучно. Уверенный пользователь ПК