Выкинуть глобальные переменные.
Что касается имен: i, j, x — нормальная практика, хотя обычно с i и j идет какая-нибудь k. lng — тоже все ясно. Вот с i18n.t явно надо что-то делать, ибо она берется откуда-то извне, непонятно, что делает и к чему относится. Можно, конечно, догадаться, что это объект интернационализации, возвращающий заданное значение на текущем языке, но все же. Если не оформлять все это в объект отдельный, то хотя бы в качестве параметров функций такие вещи передавать стоит, может, читабельнее станет код.
А вот сам по себе цикл в shuffle() читается ужасно. И не в именовании дело, а в оформлении.
buttons.push(painters[0]);
buttons.push(painters[1]);
buttons.push(painters[2]);
buttons.push(painters[3]);
...
document.getElementById("btn1").innerHTML = buttons[0];
document.getElementById("btn2").innerHTML = buttons[1];
document.getElementById("btn3").innerHTML = buttons[2];
document.getElementById("btn4").innerHTML = buttons[3];
Тут проще обойтись циклом или forEach(). Если filter() используете, видимо, предполагается его поддержка, а значит и forEach(). Для первой части можно использовать и slice().