You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 04:24:00