plotly / plotly/plotly.py

Add support for internationalization of multilingual figures

未关闭
#2,475 2 条评论 2 个 reaction 已指派 1 人 在 GitHub 查看

@T4rk1n 已经在做这个了。

开始于 2024年7月8日。

feature P3
主要语言
Python
星标
18.8k
派生
2.8k
平均合并
16 小时 26 分钟
30 天内合并 PR
21

描述

Hello! This feature request comes from a project that uses Dash, but the problems/changes are in plotly modules so I opened the ticket here.

Context: The goal is to render a dashboard with various figures (graphs and maps) in different languages. At the moment, it is required to build 4 Dash layouts to serve 4 languages, making development less convenient (can’t use standard translation tools) and requiring 4 times the memory for hosting (this was profiled). I am not the author of the project, but for a hackathon I looked at using the Flask i18n extension, and found out that Dash is not directly compatible; then after finding a compat trick, I found out that it wasn‘t enough.

Details:
This is a Dash app https://github.com/jeremymoreau/covid19mtl/blob/master/app/__init__.py viewable at https://covid19mtl.ca/en . (It’s not using latest plotly or dash for stability or familiarity I suppose.)

1) I looked for Flask i18n guides and tried to add Flask-i18n which uses a classic gettext approach with a LazyString class that is rendered to a localized string at request time.

https://github.com/jeremymoreau/covid19mtl/pull/21/files#diff-1f9f743421417fb2794c88447083a031R12-R27

LazyString was rejected during JSON encoding. I looked at this method https://github.com/plotly/plotly.py/blob/v4.6.0/packages/python/plotly/_plotly_utils/utils.py#L100 which led me to define as_plotly_json https://github.com/jeremymoreau/covid19mtl/pull/21/files#diff-828aeb2697b4cf1e4ba7120b38810cccR5-R9 to be compatible, and it worked for Dash HTML components (example https://github.com/jeremymoreau/covid19mtl/pull/21/files#diff-4599052b1ffcd344c72d72ce59a64186R399 — this is in template.py file that github hides by default even if there is a line link ☹️)

Now, how to upstream this? plotly doesn’t know about flask, but dash itself doesn’t transform to JSON, that code is in _plotly_utils and is not extensible, so I couldn’t send a quick PR. «Not extensible» I mean that a list of conversion functions is hard-coded and tried in order. Other approaches like Pyramid’s adapters or https://pypi.org/project/json-encoder/ based on single-dispatch can be extended from downstream code. But these rely on types (object class), whereas the existing approach checks for the presence of attributes (special method like tolist) or special values (pandas funky NaN and such).

Would you be open to reworking this? I think a hybrid approach could work (detect special methods like as_plotly_json or fancy scipy stack objects first, then delegate to a single-dispatched function that checks types to handle datetime, decimal, etc, and expose that function so that Dash can register a conversion function for the LazyString type.

2) The LazyString class is rejected by checks in plotly figure classes, so we can’t translate all the labels. This blocked my efforts. I didn’t try to make a str subclass because built-in classes often have shortcuts in codebases (starting with CPython itself!) so your overriden methods are not getting called when you expect and it’s a dead end. We didn’t try applying translations using JavaScript because it would require to write more gettext integration, and some of the labels are inside SVG sub-documents which wouldn’t be easy to get.

How can we satisfy plotly type checks when passing a custom class that should be transformed (i.e. call str) at render time?

Thanks for reading and considering this! I am sure more than one person would like to make multilingual plots and dashboards, so it would be great if I could contribute some useful code upstream.

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。