Hi all,
I’m using Plotly Dash to create an app. In this app I would like to change some words from language DE to EN.
I would like to use a flag for selecting the language. Is it possible?
regards
Torsten
Hi all,
I’m using Plotly Dash to create an app. In this app I would like to change some words from language DE to EN.
I would like to use a flag for selecting the language. Is it possible?
regards
Torsten
Hey @Torsten, yes thats possible.
Usually you store the words to translate in a json file in the assets folder. See also:
Another option for creating a multi-language app is to make a container and put the content of your app in this container. For generating the content of the container you do something like
def render_app_content(language: str = "en") -> html.Div:
return html.Div([.. app content here ...])
The language selection is done in a dropdown, and you create a callback that rerenders the app content whenever the language selection changes.
For the translation part, you can use the i18n
library.
Whenever you have text that you want to be translated you use something like
i18n.t("general.input_table_title", locale=language)
You create the different translations in a path, locale
for example. If you use yaml format, you name the files <namespace>.<lang_code>.yml
, so for the above example to work, you have general.en.yml
and general.de.yml
in the locale
directory.
The content of the yml file looks like
---
<lang_code>:
<var_name>: <text content>
so for the example above you have
# general.en.yml
---
en:
input_table_title: Important table
# general.de.yml
---
de:
input_table_title: Wichtiger Tisch
You set up i18n
with
i18n.set('load_path', [<path_to_locale_directory>])
Bonus:
You can use Dash iconify for the country flags
flag_icons_tag = "flag:<code>-4x3"
country_codes = {"gb": "en", "de": "de"}
language_dropdown_config = {
'default': "en",
'options': [
{
"label": DashIconify(
icon=flag_icons_tag.replace("<code>", country_code)
),
"value": language_code,
}
for country_code, language_code in country_codes.items()
]
}
Hi Tobs,
Thank you for this response. I will try this in the next 5 days. I will keep you informed here.
Best regards
Torsten
Hello Tobs,
sorry,I haven’t quite understood it yet. Could you perhaps create a small example for me?
This here is what I have yet. Only a small app.
import dash
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
from datetime import datetime, timedelta
import dash_bootstrap_components as dbc # pip install dash-bootstrap-components
from dash_iconify import DashIconify
from flask import Flask
from waitress import serve
server = Flask(__name__)
app = dash.Dash(__name__,
meta_tags=[{"name": "viewport", "content": "width=device-width, initial-scale=1"}],
server=server)#,external_stylesheets=[dbc.themes.SLATE])
server = app.server
app.layout = html.Div([
dbc.Row([
dcc.Dropdown(['DE', 'EN', 'IT'], 'DE', id='language-dropdown'),
]),
dbc.Row([
html.Div([
html.H4(id='textarea-example', style={'color': 'blue'})
])
]),
])
@app.callback(
Output('textarea-example', 'children'),
Input('language-dropdown', 'value'))
def update_app(lang):
val = f"es wurde {lang} gewählt"
return val
if __name__ == '__main__':
app.run_server(debug=False, port=5555)
Thanks
Torsten
Hi @Torsten,
Below I added a minimal app and three yml files. Create a locale
directory next to your app.py
and put the three yml files in there:
- project_dir
|- locale
| |- general.de.yml
| |- general.en.yml
| |- general.it.yml
|- app.py
I added three example texts in there, one static text sample, one text sample with a variable in it and one text sample that is updated via a callback. So you get an idea of what is possible.
Note: Looking at your example, you are using the old way of importing things from Dash. Look at the included example to see what the latest import system looks like.
Note 2: You are explicitly creating a server, unless you need to do things with the Flask server, you can ignore that.
Since we are working with yml files, make sure to install i18n like:
pip install python-i18n[YAML]
# app.py
from pathlib import Path
import dash
from dash import Input, Output, State, dcc, html, callback
import dash_bootstrap_components as dbc
from dash_iconify import DashIconify
import i18n
app = dash.Dash(
__name__,
)
i18n.set("load_path", [str(Path(__file__).parent / "locale")])
flag_icons_tag = "flag:<code>-4x3"
country_codes = {"gb": "en", "de": "de", "it": "it"}
language_dropdown_config = {
"default": "en",
"options": [
{
"label": DashIconify(icon=flag_icons_tag.replace("<code>", country_code)),
"value": language_code,
}
for country_code, language_code in country_codes.items()
],
}
def render_app_content(language: str = "en") -> dbc.Row:
return dbc.Row(
[
dbc.Col(
[
html.H4(
id="textarea-example",
children=[i18n.t("general.welcome_message", locale=language)],
style={"color": "blue"},
),
html.Div(
id="dynamic_text",
children=[
i18n.t(
"general.dynamic_text", locale=language, lang=language
)
],
),
dbc.Button(
id="button",
children="Count clicks",
),
html.Div(
id="callback_update",
children=[],
),
]
)
]
)
app.layout = dbc.Container(
[
dbc.Row(
[
dcc.Dropdown(
options=language_dropdown_config["options"],
value=language_dropdown_config["default"],
id="language-dropdown",
style={"width": "60px"},
clearable=False,
),
]
),
dbc.Container(
id="app_container",
children=[render_app_content(language=language_dropdown_config["default"])],
),
],
)
@callback(
Output("app_container", "children"),
Input("language-dropdown", "value"),
)
def update_app(selected_language: str) -> dbc.Row:
return render_app_content(language=selected_language)
@callback(
Output("callback_update", "children"),
Input("button", "n_clicks"),
State("language-dropdown", "value"),
)
def count_clicks(n_clicks: int, language: str) -> str:
if not language:
language = language_dropdown_config["default"]
return i18n.t("general.callback_update", locale=language, count=n_clicks)
if __name__ == "__main__":
app.run_server(debug=True)
# general.en.yml
en:
welcome_message: Welcome to our site!
dynamic_text: "You have selected %{lang}"
callback_update: You have clicked the button %{count} times
# general.de.yml
de:
welcome_message: Willkommen auf unserer Seite!
dynamic_text: "Es wurde %{lang} gewählt"
callback_update: Sie haben den Button %{count} Mal geklickt
# general.it.yml
it:
welcome_message: Benvenuti sul nostro sito!
dynamic_text: "Hai selezionato %{lang}"
callback_update: Hai cliccato il pulsante %{count} volte
Hi Tobs,
Thanks a lot for this demo app. Now I know how it works.
BR
Torsten