pierrejeambrun opened a new pull request, #72648:
URL: https://github.com/apache/airflow/pull/72648

   Plugins can now contribute UI translations, letting a deployment localize 
the Airflow UI into a language it does not ship, or override specific strings, 
without forking the frontend.
   
   A plugin declares a `ui_translations` list whose entries are either a 
`<language>/<namespace>.json` directory tree or an inline `{language: 
{namespace: {key: value}}}` mapping (the two can be mixed). Each entry is 
deep-merged over the built-in translations, so an override replaces only the 
keys it names — at any nesting depth — and everything else falls back to the 
built-in language, and ultimately English.
   
   ```python
   from pathlib import Path
   
   from airflow.plugins_manager import AirflowPlugin
   
   
   class TranslationsPlugin(AirflowPlugin):
       name = "translations"
       ui_translations = [
           Path(__file__).parent / "locales",          # 
<language>/<namespace>.json tree
           {"en": {"dags": {"dag_one": "Pipeline"}}},   # inline override of 
specific keys
       ]
   ```
   
   ### Robustness (translations are not versioned in lockstep with Airflow)
   
   - A broken translation source (unreadable file, malformed JSON, a bad 
`ui_translations` value) is skipped with a warning. It never stops the API 
server from starting or keeps other plugins from loading.
   - English is the reference for which keys exist. At consolidation time, a 
plugin key that is not present in the English file for its namespace is logged 
as a warning (it was likely renamed or removed upstream) and otherwise ignored.
   
   ### Right-to-left languages
   
   Text direction is derived from the locale (the browser's CLDR data), so a 
custom RTL language flips the whole UI to right-to-left automatically, with no 
extra configuration.
   
   ### How it works
   
   - **Backend:** a route serves each locale file with the plugin overrides 
deep-merged in. It stays unauthenticated because translations must load before 
login (the login page is localized too), and is only registered when a plugin 
actually contributes translations, so deployments without such a plugin keep 
serving the bundled files straight from the static mount. A small manifest 
route lists the plugin languages.
   - **Frontend:** the extra languages extend i18next's `supportedLngs` and 
appear in the language selector (names resolved via `Intl.DisplayNames`).
   
   ### Screenshots
   
   Demonstrated with a local plugin adding **Esperanto** (LTR, from a directory 
tree), **Persian** (RTL, from a directory tree), and **English** overrides 
(inline Python dict).
   
   Inline Python override — the Admin menu shows "Pools!" instead of "Pools":
   
   ![Inline override in 
English](https://raw.githubusercontent.com/astronomer/airflow/pr-i18n-translations-screenshots/01-inline-override-en-admin-menu.png)
   
   Custom LTR language (Esperanto) from full files — the Admin menu shows 
Naĝejoj / Variabloj, with English fallback for untranslated items:
   
   ![Esperanto, 
LTR](https://raw.githubusercontent.com/astronomer/airflow/pr-i18n-translations-screenshots/02-esperanto-ltr-admin-menu.png)
   
   Custom RTL language (Persian) from full files — the whole UI flips to 
right-to-left:
   
   ![Persian, 
RTL](https://raw.githubusercontent.com/astronomer/airflow/pr-i18n-translations-screenshots/03-persian-rtl-admin-menu.png)
   
   The language selector lists the plugin languages (Esperanto, فارسی) 
alongside the built-ins:
   
   ![Language 
selector](https://raw.githubusercontent.com/astronomer/airflow/pr-i18n-translations-screenshots/04-language-selector-lists-plugin-languages.png)
   
   ---
   
   ##### Was generative AI tooling used to co-author this PR?
   
   - [X] Yes — Claude Code (Opus 4.8)
   
   Generated-by: Claude Code (Opus 4.8) following [the 
guidelines](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to