Активные языки моего веб-приложения хранятся в Java List, и этот список доступен Thymeleaf.
Снаружи тега <style> это просто и работает как шарм:
<button th:each = "lang : ${ activeLanguages }" th:data-lang = "${ lang.languageTag }" onclick = "setLang( this );">
<span th:text = "${ lang.localName }"></span>
</button>
Можно ли выпустить тег th:each внутри <style>, чтобы избежать жесткого кодирования активных языков в классах CSS?
Вот как у меня пока:
<style>
.Flag.IE { background-image:url("/IE.svg"); }
.Flag.HR { background-image:url("/HR.svg"); }
.Flag.EN { background-image:url("/EN.svg"); }
</style>
Это то, что я хочу (хорошо, не совсем это, а решение таким образом):
<style>
---> th:each = "lang : ${ activeLanguages }" <---
.Flag.${ lang.iso2Country.toUpperCase() } {
background-image:url("/${ lang.iso2Country.toUpperCase() }.svg");
}
---> th:each END <---
</style>
Обновлено: у меня есть рабочее решение, но оно очень уродливое:
<style th:each = "lang : ${ webData.activeLanguages }">
.Flag.[[ ${ lang.iso2Country.toUpperCase() } ]]::before {
background-image:url("/[[ ${ lang.iso2Country.toUpperCase()} ]]");
}
</style>




Считаете ли вы это менее уродливым или нет, это, вероятно, субъективно...
Вы можете использовать CSS-инлайнинг, объявив тег стиля следующим образом:
<style th:inline = "css">
...
</style>
А затем вы можете объединить это с текстовой встроенной итерацией, аналогично тому, что показано в этом разделе документации:
<style th:inline = "css">
[# th:each = "lang : ${activeLanguages}"]
[#th:block th:utext = "|.Flag.${lang.languageTag} \{|" /]
[#th:block th:utext = "|background-image: url('${lang.languageTag}.svg');|" /]
[#th:block th:utext = "|}|" /]
[/]
</style>
Это создает HTML, подобный следующему:
<style>
.Flag.XY {
background-image: url('XY.svg');
}
.Flag.AB {
background-image: url('AB.svg');
}
</style>
ВНИМАНИЕ! для этого необходимо использовать th:utext, что несет в себе угрозу безопасности, если оно обрабатывает НЕДОВЕРЕННЫЕ данные, предоставленные пользователем. Но если у вас есть собственный заранее определенный список языков (пользователи не могут «предоставить» эти значения, они могут выбрать только один из них), тогда текст, используемый для переменных Thymeleaf, должен быть безопасным. Но убедиться в том, что это так, зависит от вас.
ОБНОВЛЕНИЕ - более лаконично и безопаснее
Есть более краткий способ сделать это:
<style th:inline = "css">
[# th:each = "lang : ${activeLanguages}"]
.Flag.[[${lang.languageTag}]] {
background-image: url("/[[${lang.languageTag}]].svg");
}
[/]
</style>
Здесь встроенный текст на самом деле представляет собой обычный текст, а переменные Thymeleaf вставляются между [[ и ]].
Результаты:
<style>
.Flag.XY {
background-image: url("/XY.svg");
}
.Flag.AB {
background-image: url("/AB.svg");
}
</style>
Что еще хорошо в этом, так это то, что мы можем использовать [[...]] вместо [(...)] — это означает, что любой потенциально опасный контент в ${...} будет безопасно экранирован рендерером Thymeleaf.
Так что мое предыдущее предупреждение не относится к этому подходу.
О да, это то, что я хотел получить! Я использовал термин «уродливый», потому что мое решение создает отдельный блок стилей для каждого языка вместо того, чтобы создавать один блок стилей и помещать в него все языки.