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

Shiny.i18n实时翻译带HTML格式文本异常问题求助

问题根因

shiny.i18n的update_lang前端自动翻译逻辑,默认只会扫描DOM中的纯文本节点做key匹配。如果直接在翻译key里嵌入<strong>这类HTML标签,浏览器渲染时会把整段文本拆成标签节点、文本节点等多个独立子元素,前端无法找到和整句key完全匹配的纯文本节点,就会出现带标签内容完全不触发翻译的问题。
两种错误写法的具体原因:

  • 写法h1(i18n$t(HTML("<strong>Hallo</strong> Welt"))):传入i18n$t()的是shiny的HTML类对象,不是纯字符向量,翻译函数无法识别非字符串输入,直接返回原内容,自然不会触发多语言替换
  • 写法h1(HTML(i18n$t("<strong>Hallo</strong> Welt"))):初始渲染时虽然能拿到翻译结果,但节点被标记为原生HTML内容后,前端自动翻译逻辑会直接跳过该节点,部分旧版本shiny.i18n还会因为类型校验不通过,抛出argument is not a character vector的错误。
无拆分实现方案(保留长文本上下文)

采用「纯文本翻译+后置样式替换」的思路,不在翻译文件中嵌入原生HTML标签,用轻量标记标注需要加粗的词汇,翻译完成后统一替换为HTML样式标签,完全避免DOM节点拆分导致的匹配失败问题。

步骤1:修改翻译配置文件

用markdown通用的**词汇**格式标记需要加粗的内容,去掉原生HTML标签,修改后的translation.json如下:

{
   "languages":["de", "en"],
   "translation":[
      {
         "de":"**Hallo** Welt",
         "en":"**Hello** World"
      },
      {
         "de":"Sprache ändern:",
         "en":"Change language:"
      },
      {
        "de":"Welt",
        "en":"World"
      }
   ]
}

步骤2:编写通用翻译辅助函数

自定义带样式处理的翻译函数,先完成纯文本翻译,再将加粗标记替换为HTML的<strong>标签,最终返回可直接渲染的HTML对象:

# 带加粗样式的翻译函数
t_rich <- function(text_key) {
  # 先执行纯文本翻译
  raw_trans <- i18n$t(text_key)
  # 替换**标记为加粗HTML标签
  rich_trans <- gsub("\\*\\*(.*?)\\*\\*", "<strong>\\1</strong>", raw_trans)
  # 返回可渲染的HTML内容
  HTML(rich_trans)
}

步骤3:适配实时语言切换

因为带样式的富文本内容无法被前端自动翻译扫描识别,需要将这类内容放到renderUI中做响应式渲染,确保切换语言时能实时更新,完整可运行代码如下:

library(shiny)
library(shiny.i18n)

i18n <- Translator$new(translation_json_path='translation.json')
i18n$set_translation_language('de')

t_rich <- function(text_key) {
  raw_trans <- i18n$t(text_key)
  rich_trans <- gsub("\\*\\*(.*?)\\*\\*", "<strong>\\1</strong>", raw_trans)
  HTML(rich_trans)
}

ui <- fluidPage(
  shiny.i18n::usei18n(i18n),
  h1(i18n$t("Welt")),
  tags$div(
    style='float: right;',
    selectInput(
      inputId='selected_language',
      label=i18n$t('Change language'),
      choices = i18n$get_languages(),
      selected = i18n$get_key_translation()
    )
  ),
  # 富文本翻译内容用uiOutput承接
  uiOutput("welcome_title")
)


server <- function(input, output, session) {
  # 切换语言时同步更新i18n实例的语言配置
  observeEvent(input$selected_language, {
    i18n$set_translation_language(input$selected_language)
    update_lang(session, input$selected_language)
  })
  
  # 响应式渲染带加粗的富文本标题
  output$welcome_title <- renderUI({
    h1(t_rich("**Hallo** Welt"), windowTitle=NULL)
  })
}

shinyApp(ui = ui, server = server)
方案优势
  • 不需要将长文本拆分为独立词汇逐个翻译,完整保留上下文语义,翻译文件维护成本低
  • 翻译配置中不嵌入原生HTML代码,不会触发DOM节点拆分导致的翻译匹配失败问题
  • 样式规则统一收敛在辅助函数中,后续需要新增斜体、高亮等其他样式时,只需要修改替换规则即可,不需要调整翻译内容

内容的提问来源于stack exchange,提问作者LauraFeh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 05:15:54