Vaadin 21 Grid切换会话Locale时LocalDateTimeRenderer日期格式不更新如何解决
Vaadin 21中的LocalDateTimeRenderer即便在Vaadin会话的Locale修改为Locale.UK等其他值时,仍会在德语浏览器中显示德语格式的日期。
我在Vaadin 21的Grid组件中设置了LocalDateTime类型的列,针对实体类型T的创建代码如下:
private <T> Column<T> addLocalDateTimeColumn(Grid<T> grid, ValueProvider<T, LocalDateTime> getter) { LocalDateTimeRenderer<T> renderer = new LocalDateTimeRenderer(getter); Column<T> column = grid.addColumn(renderer).setAutoWidth(true); return column; }
当我调用UI.getCurrent().getSession().setLocale(locale);修改会话的Locale时,整个应用都会切换为对应新语言的翻译内容,但LocalDateTime列的内容不会同步变更格式。
我尝试调用grid.getDataProvider().refreshAll()刷新整个Grid,可以触发上述代码中的ValueProvider重新执行,但LocalDateTime仍未按照新选择的语言格式化,不符合预期。
因此即便会话的Locale是英语Locale.UK,LocalDateTime值仍以德语格式显示:
我也尝试使用本地化的DateTimeFormatter创建渲染器:LocalDateTimeRenderer<T> renderer = new LocalDateTimeRenderer(getter, DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL, FormatStyle.SHORT));,仍然无效:仅格式样式发生变化,月份仍为德语翻译。
目前使用自定义的TextRenderer可以实现需求(即LocalDateTime列的内容会随会话Locale同步切换翻译),实现代码如下:
private <T> Column<T> addLocalDateTimeColumn(Grid<T> grid, ValueProvider<T, LocalDateTime> getter) { Renderer<T> renderer = new TextRenderer<T>(new ItemLabelGenerator<T>() { @Override public String apply(T entity) { final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd. MMMM yyyy HH:mm", UI.getCurrent().getLocale()); return getter.apply(entity).format(formatter); } }); Column<T> column = grid.addColumn(renderer).setAutoWidth(true); return column; }
请问有没有办法直接使用Vaadin原生的LocalDateTimeRenderer实现相同的Locale同步适配效果?
你遇到的问题是因为Vaadin 21的LocalDateTimeRenderer默认会在初始化时固定使用当前的Locale,后续不会主动监听会话Locale的变更,所以就算刷新数据也不会更新日期格式。直接使用原生LocalDateTimeRenderer可以通过以下两种方案实现Locale同步:
方案1:使用带动态Locale提供者的构造方法(推荐)
LocalDateTimeRenderer提供了支持动态Locale的重载构造参数,你只需要传入格式规则和动态获取当前会话Locale的供应函数即可,每次渲染单元格时都会自动取最新的Locale进行格式化:
private <T> Column<T> addLocalDateTimeColumn(Grid<T> grid, ValueProvider<T, LocalDateTime> getter) { LocalDateTimeRenderer<T> renderer = new LocalDateTimeRenderer<>( getter, "dd. MMMM yyyy HH:mm", () -> UI.getCurrent().getLocale() ); Column<T> column = grid.addColumn(renderer).setAutoWidth(true); return column; }
切换Locale后只需要调用grid.getDataProvider().refreshAll()就能刷新所有日期的显示格式,不需要额外改造逻辑。
方案2:Locale变更时重新设置Renderer
如果你需要用DateTimeFormatter自定义复杂格式,也可以在每次切换Locale后,为对应列重新创建带新Locale的LocalDateTimeRenderer:
// 切换Locale时执行的逻辑 public void updateDateTimeColumnAfterLocaleChange(Locale newLocale) { UI.getCurrent().getSession().setLocale(newLocale); DateTimeFormatter formatter = DateTimeFormatter .ofLocalizedDateTime(FormatStyle.FULL, FormatStyle.SHORT) .withLocale(newLocale); // 为日期列重新设置Renderer dateTimeColumn.setRenderer(new LocalDateTimeRenderer<>(getter, formatter)); grid.getDataProvider().refreshAll(); }
内容的提问来源于stack exchange,提问作者sdo

