Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
149 commits
Select commit Hold shift + click to select a range
df85633
feat: add IBM Globalization Pipeline integration and i18n setup
RamGopalSrikar Mar 18, 2026
fa4f0b8
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 18, 2026
f0fd004
fix: resolve ruff linting issues in GP scripts
RamGopalSrikar Mar 18, 2026
25df0d7
feat: migrate all frontend UI strings to i18n for GP localization
RamGopalSrikar Mar 18, 2026
53e6e7e
feat: migrate sidebar strings to i18n (Phase 4)
RamGopalSrikar Mar 18, 2026
55d537d
Merge branch 'release-1.9.0' into feat/globalization-pipeline
RamGopalSrikar Mar 20, 2026
d51825d
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 20, 2026
cbee23c
fix: add react-i18next mock and fix sidebar nav tests for i18n migration
RamGopalSrikar Mar 23, 2026
7855bd8
Merge branch 'release-1.9.0' into feat/globalization-pipeline
RamGopalSrikar Mar 23, 2026
e37bce5
Merge branch 'release-1.9.0' into feat/globalization-pipeline
RamGopalSrikar Mar 23, 2026
3c71503
feat: add LanguageSelector dropdown to globalization pipeline
RamGopalSrikar Mar 23, 2026
23e0b3c
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 23, 2026
482f95a
ci: add GP_TEST environment to gp-download and gp-upload workflows
RamGopalSrikar Mar 24, 2026
e52f826
temp: add feature branch push trigger for workflow testing
RamGopalSrikar Mar 24, 2026
aed1a8d
temp: trigger gp-upload workflow test
RamGopalSrikar Mar 24, 2026
8db402f
fix: use correct GP_test environment name in workflows
RamGopalSrikar Mar 24, 2026
ea9aa7a
fix: use vars for GP_INSTANCE and GP_BUNDLE
RamGopalSrikar Mar 24, 2026
21e5a7c
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 24, 2026
458457f
fix: correct environment name to GP-test (hyphen not underscore)
RamGopalSrikar Mar 24, 2026
6b0aa55
chore: update translations from Globalization Pipeline [skip ci]
github-actions[bot] Mar 24, 2026
f8cc7f3
Merge branch 'release-1.9.0' into feat/globalization-pipeline
RamGopalSrikar Mar 24, 2026
22fda69
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 24, 2026
9b2c83f
chore: update translations from Globalization Pipeline [skip ci]
github-actions[bot] Mar 24, 2026
f710607
temp: trigger gp-upload workflow test
RamGopalSrikar Mar 24, 2026
83c6894
ci: add download-gp-bundle job to nightly build pipeline
RamGopalSrikar Mar 24, 2026
956bc62
chore: remove temporary dev files from gp scripts directory
RamGopalSrikar Mar 24, 2026
518180a
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 24, 2026
c590977
chore: update translations from Globalization Pipeline [skip ci]
github-actions[bot] Mar 24, 2026
3a8a76d
Merge branch 'release-1.9.0' into feat/globalization-pipeline
RamGopalSrikar Mar 26, 2026
f7c584f
Merge branch 'release-1.9.0' into feat/globalization-pipeline
RamGopalSrikar Mar 26, 2026
48f7ea4
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 26, 2026
ae7a214
chore: update translations from Globalization Pipeline [skip ci]
github-actions[bot] Mar 26, 2026
e691da8
feat(i18n): move language selector from account menu to Settings > Ge…
RamGopalSrikar Mar 26, 2026
a4540bb
feat(i18n): refactor language constants and improve GP pipeline
RamGopalSrikar Mar 26, 2026
945a819
Merge branch 'release-1.9.0' into feat/globalization-pipeline
RamGopalSrikar Mar 26, 2026
852fb03
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 26, 2026
328bba7
ci(gp): trigger upload on release branches, download via dispatch only
RamGopalSrikar Mar 27, 2026
f90dab0
chore: update translations from Globalization Pipeline
RamGopalSrikar Mar 27, 2026
d6434df
fix(i18n): address PR review comments — tests, nightly build decoupli…
RamGopalSrikar Mar 27, 2026
99ee7a3
feat(i18n): lazy-load non-English locale files via Vite dynamic imports
RamGopalSrikar Mar 27, 2026
34a5b82
Merge remote-tracking branch 'origin/release-1.9.0' into feat/globali…
RamGopalSrikar Mar 27, 2026
02ca489
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 27, 2026
247120c
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] Mar 27, 2026
51ad17f
fix: add ruff ignores for scripts/gp/tests
RamGopalSrikar Mar 27, 2026
c298244
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 27, 2026
3d3a943
fix(ci): run GP translation download before nightly tag creation
RamGopalSrikar Mar 27, 2026
aac79b1
fix(ui): replace native select with Radix UI Select in LanguageForm
RamGopalSrikar Apr 1, 2026
c12ce38
feat: backend i18n — serve translated component metadata via Accept-L…
RamGopalSrikar Apr 6, 2026
1d29413
Merge remote-tracking branch 'origin/release-1.9.0' into feat/gp-back…
RamGopalSrikar Apr 8, 2026
c3787a5
chore: auto-regenerate backend locales/en.json [skip ci]
github-actions[bot] Apr 8, 2026
301f7a3
Merge branch 'release-1.9.0' into feat/gp-backend-i18n-clean
RamGopalSrikar Apr 9, 2026
a472dc5
chore: auto-regenerate backend locales/en.json [skip ci]
github-actions[bot] Apr 9, 2026
e4654fe
refactor: simplify GP backend workflows to remove duplication
RamGopalSrikar Apr 9, 2026
9d93af9
feat: add nightly backend translation download job to gp-download wor…
RamGopalSrikar Apr 9, 2026
87941ed
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 9, 2026
04b087a
fix: skip backend translation download on nightly schedule
RamGopalSrikar Apr 9, 2026
fcfa546
fix: remove backend GP download from nightly build workflow
RamGopalSrikar Apr 9, 2026
e1c9717
fix: remove frontend GP download from nightly build workflow
RamGopalSrikar Apr 9, 2026
b533dec
fix: remove en.json from check workflow trigger paths
RamGopalSrikar Apr 9, 2026
7ea27ee
fix: mock lfx.components in sys.modules for collect_strings test
RamGopalSrikar Apr 9, 2026
b7d3080
fix: resolve ruff violations in GP scripts and main.py
RamGopalSrikar Apr 9, 2026
717108a
feat(i18n): sync canvas node translations on language change
RamGopalSrikar Apr 9, 2026
00cb73e
Merge branch 'release-1.9.0' into feat/gp-backend-i18n-clean
RamGopalSrikar Apr 9, 2026
b3b9a33
feat(i18n): translate Templates modal and starter flow metadata
RamGopalSrikar Apr 13, 2026
925ebdd
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 13, 2026
a8c4cb4
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] Apr 13, 2026
dbc9c4b
feat(i18n): translate MCP Server tab and fix sidebar category truncation
RamGopalSrikar Apr 13, 2026
9879647
feat(i18n): translate Knowledge, Files pages and fix sidebar overflow
RamGopalSrikar Apr 13, 2026
826e0e6
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 13, 2026
ce5a6b4
feat(i18n): translate delete confirmation modal and fix CTA button ov…
RamGopalSrikar Apr 13, 2026
bd070ca
feat(i18n): translate Create Knowledge Base modal and flow dropdown menu
RamGopalSrikar Apr 13, 2026
c3030dc
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 13, 2026
2aa192f
fix(i18n): use min-height for Knowledge Base modal to prevent scroll …
RamGopalSrikar Apr 13, 2026
e8cac7f
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 13, 2026
8e85149
feat(i18n): translate StepperModal footer buttons (Next Step, Back, N…
RamGopalSrikar Apr 13, 2026
ed2e32f
feat(i18n): translate model input dropdown (No Models Enabled, Refres…
RamGopalSrikar Apr 13, 2026
1e94ebe
feat(i18n): translate Model Providers modal (config form, model selec…
RamGopalSrikar Apr 14, 2026
4bbe1b3
feat(i18n): translate starter template note/README nodes at serve-time
RamGopalSrikar Apr 14, 2026
f4d9c26
feat(i18n): translate canvas note nodes on language change via dedica…
RamGopalSrikar Apr 14, 2026
89f286f
feat(i18n): fix Playground/Share button overlap and translate Share b…
RamGopalSrikar Apr 14, 2026
a6827a4
feat(i18n): translate input placeholder and info fields for backend c…
RamGopalSrikar Apr 14, 2026
025d8d5
feat(i18n): translate Share dropdown items (API access, Export, MCP S…
RamGopalSrikar Apr 14, 2026
5c0cc5c
fix(i18n): stamp i18n_key in translate_flow_notes and remove dead sta…
RamGopalSrikar Apr 15, 2026
316afd9
refactor(i18n): bake i18n_key into template noteNodes, remove runtime…
RamGopalSrikar Apr 15, 2026
fde0de6
ci(i18n): auto-bake note keys on template JSON changes in CI
RamGopalSrikar Apr 15, 2026
c491775
refactor(i18n): replace index-based note keys with content-hash keys
RamGopalSrikar Apr 15, 2026
a08102c
fix(i18n): thread-safe translation loading and correct falsy key check
RamGopalSrikar Apr 15, 2026
dd26eb9
feat(i18n): translate Settings page UI strings across multiple sections
RamGopalSrikar Apr 15, 2026
44a4d74
fix(i18n): replace fixed card heights with min-h to prevent layout is…
RamGopalSrikar Apr 15, 2026
fd90eb5
feat(i18n): translate SaveChangesModal (unsaved changes popup)
RamGopalSrikar Apr 16, 2026
9f71a3a
chore(i18n): download updated frontend and backend translations from GP
RamGopalSrikar Apr 16, 2026
48e6fa3
feat(i18n): translate ToolsModal (URL/tools selection popup)
RamGopalSrikar Apr 16, 2026
b3cf1a3
chore(i18n): download updated frontend translations from GP
RamGopalSrikar Apr 16, 2026
dc980e8
feat(i18n): translate MCP Client settings page, shareable playground …
RamGopalSrikar Apr 16, 2026
7393528
feat(i18n): translate MCP Server Auth modal (authModal)
RamGopalSrikar Apr 16, 2026
a044b8a
feat: add translation keys for MCP JSON configuration
RamGopalSrikar Apr 16, 2026
81b87d1
feat(i18n): translate project delete notification, MCP install notifi…
RamGopalSrikar Apr 17, 2026
1ac614e
feat(i18n): translate default flow/project names and delete notificat…
RamGopalSrikar Apr 17, 2026
0e2f221
refactor(i18n): content-hash component keys and normalize frontend lo…
RamGopalSrikar Apr 17, 2026
28716b1
feat(i18n): fix legacy component alias translation and translate file…
RamGopalSrikar Apr 17, 2026
e591fcb
feat(i18n): translate canvas controls and Model Providers page strings
RamGopalSrikar Apr 18, 2026
865621a
feat(i18n): translate upload folder button and model trigger strings
RamGopalSrikar Apr 18, 2026
3e28e65
feat(i18n): cache /basic_examples/ translations per locale
RamGopalSrikar Apr 20, 2026
06e2b83
feat(i18n): translate NoteNode empty placeholder text
RamGopalSrikar Apr 20, 2026
d2310df
feat(i18n): translate slider labels, model trigger, dropdown loading,…
RamGopalSrikar Apr 20, 2026
281a286
feat(i18n): translate model provider toast notifications
RamGopalSrikar Apr 20, 2026
e04295f
fix(i18n): address PR review — DRY key functions, locale allow-list, …
RamGopalSrikar Apr 20, 2026
0f4d36a
refactor(gp): consolidate upload/download scripts with --target flag
RamGopalSrikar Apr 20, 2026
607e0d4
Merge remote-tracking branch 'origin/release-1.10.0' into feat/gp-bac…
RamGopalSrikar Apr 22, 2026
dbd1f45
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 22, 2026
c189b4b
chore(starter-projects): sync starter project snapshots with release-…
RamGopalSrikar Apr 22, 2026
d6d769e
chore: auto-bake note keys and regenerate backend locales/en.json [sk…
github-actions[bot] Apr 22, 2026
11f55bb
feat(i18n): restore LanguageForm component in Settings > General page
RamGopalSrikar Apr 22, 2026
3e8e596
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 22, 2026
7b90f08
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] Apr 22, 2026
5c380e0
fix(projects): always use English for new project names
RamGopalSrikar Apr 22, 2026
0fb68d3
chore(i18n): download missing Vector Store RAG note translations
RamGopalSrikar Apr 22, 2026
28842e8
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 22, 2026
fa0f740
fix(canvas): fix zoom dropdown shortcut layout on Windows
RamGopalSrikar Apr 22, 2026
78eb4d9
fix(i18n): sync tooltip info and placeholder fields for existing canv…
RamGopalSrikar Apr 22, 2026
68906db
fix(i18n): persist language selection across page refreshes
RamGopalSrikar Apr 22, 2026
1580a93
fix(sidebar): add tooltip to truncated category header labels
RamGopalSrikar Apr 22, 2026
6c44edd
fix(sidebar): add tooltip to truncated discover more components button
RamGopalSrikar Apr 22, 2026
49d82ed
fix(sidebar): add tooltips to footer buttons (new custom component, MCP)
RamGopalSrikar Apr 22, 2026
d09b74e
fix(login): center-align title to handle wrapped translations gracefully
RamGopalSrikar Apr 22, 2026
1d7c682
fix(signup): center-align title to handle wrapped translations gracef…
RamGopalSrikar Apr 22, 2026
f275f15
fix: remove tooltips from form field labels and add tooltip to sign-i…
RamGopalSrikar Apr 22, 2026
c756bf6
Merge remote-tracking branch 'origin/release-1.10.0' into feat/gp-bac…
RamGopalSrikar Apr 27, 2026
4b90541
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 27, 2026
94f3026
chore: auto-bake note keys and regenerate backend locales/en.json [sk…
github-actions[bot] Apr 27, 2026
34257c8
Merge branch 'release-1.10.0' into feat/gp-backend-i18n-clean
RamGopalSrikar Apr 27, 2026
4f0c9a0
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 27, 2026
82ea3a6
fix: resolve ruff violations in gp scripts and i18n util
RamGopalSrikar Apr 27, 2026
ad125a8
Merge branch 'release-1.10.0' into feat/gp-backend-i18n-clean
RamGopalSrikar Apr 27, 2026
b4cfba0
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 27, 2026
f7c5b7a
fix: lazy-import langflow in extract_backend_strings to fix GP test c…
RamGopalSrikar Apr 27, 2026
6bd9b35
fix(tests): mock langflow.utils.i18n_keys in test_collect_strings_ski…
RamGopalSrikar Apr 27, 2026
65c64d2
fix(frontend): restore missing modal height constant imports in Knowl…
RamGopalSrikar Apr 27, 2026
d64a8b4
Merge remote-tracking branch 'origin/release-1.10.0' into feat/gp-bac…
RamGopalSrikar Apr 27, 2026
e4ecf1f
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 27, 2026
8cfd5bc
fix(tests): add global mocks for ShadTooltip and useGetNoteTranslatio…
RamGopalSrikar Apr 27, 2026
9a2869c
Merge branch 'release-1.10.0' into feat/gp-backend-i18n-clean
RamGopalSrikar Apr 27, 2026
8a72dd2
fix(tests): add syncNodeTranslations no-op mock to flowStore in affec…
RamGopalSrikar Apr 27, 2026
c94e1f8
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 27, 2026
9f5c4db
fix(tests): use stable testId selector instead of node title text in …
RamGopalSrikar Apr 28, 2026
5dae32a
fix(i18n): preserve instance-level node display_name and description …
RamGopalSrikar Apr 28, 2026
ecc710c
Merge branch 'release-1.10.0' into feat/gp-backend-i18n-clean
RamGopalSrikar Apr 28, 2026
a42daef
chore: auto-bake note keys and regenerate backend locales/en.json [sk…
github-actions[bot] Apr 28, 2026
3479c69
Merge branch 'release-1.10.0' into feat/gp-backend-i18n-clean
RamGopalSrikar Apr 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions .github/workflows/gp-backend-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: GP Backend Auto-update Strings

on:
pull_request:
paths:
- "src/lfx/src/lfx/components/**"
- "src/backend/base/langflow/initial_setup/starter_projects/**"

jobs:
auto-commit:
if: |
github.actor != 'github-actions[bot]' &&
github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
name: Auto-regenerate locales/en.json on PR branch
permissions:
contents: write

steps:
- name: Checkout PR branch
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
token: ${{ secrets.GITHUB_TOKEN }}

- name: Bake i18n_key into template noteNodes
run: python scripts/gp/bake_note_keys.py

- name: Setup uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
cache-dependency-glob: "uv.lock"
python-version: "3.12"

- name: Install workspace (lfx + langflow-base)
run: uv sync --no-dev

- name: Generate en.json
run: uv run python scripts/gp/extract_backend_strings.py

- name: Commit updated files to PR branch if changed
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add src/backend/base/langflow/initial_setup/starter_projects/
git add src/backend/base/langflow/locales/en.json
git diff --staged --quiet || git commit -m "chore: auto-bake note keys and regenerate backend locales/en.json [skip ci]"
git push
103 changes: 102 additions & 1 deletion .github/workflows/gp-download.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
GP_ADMIN_PASSWORD: ${{ secrets.GP_ADMIN_PASSWORD }}
GP_INSTANCE: ${{ vars.GP_INSTANCE }}
GP_BUNDLE: ${{ vars.GP_BUNDLE }}
run: python download_translations.py --output ../../src/frontend/src/locales/
run: python download.py --target frontend --output ../../src/frontend/src/locales/

- name: Close stale translation PRs
uses: actions/github-script@v8
Expand Down Expand Up @@ -105,3 +105,104 @@ jobs:
- name: Report GP download failure
if: failure()
run: echo "::warning::GP translation download failed — translations may be out of date. Check the 'Download translations from GP' step above for details."

download-backend:
if: github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
name: Download backend translations from Globalization Pipeline
environment: GP-test
permissions:
contents: write
pull-requests: write

steps:
- name: Resolve latest release branch
id: resolve-branch
run: |
BRANCH=$(git ls-remote --heads https://github.com/${{ github.repository }} 'refs/heads/release-*' \
| awk '{print $2}' \
| sed 's|refs/heads/||' \
| grep -E '^release-[0-9]+\.[0-9]+\.[0-9]+$' \
| sort -V \
| tail -n 1)
if [ -z "$BRANCH" ]; then
echo "No release-* branch found in ${{ github.repository }}"
exit 1
fi
echo "branch=${BRANCH}" >> "$GITHUB_OUTPUT"
echo "Using release branch: $BRANCH"

- name: Checkout release branch
uses: actions/checkout@v4
with:
ref: ${{ steps.resolve-branch.outputs.branch }}

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install dependencies
run: pip install -r scripts/gp/requirements.txt

- name: Download backend translations from GP
working-directory: scripts/gp
env:
GP_ADMIN_USER_ID: ${{ secrets.GP_ADMIN_USER_ID }}
GP_ADMIN_PASSWORD: ${{ secrets.GP_ADMIN_PASSWORD }}
GP_INSTANCE: ${{ vars.GP_INSTANCE }}
GP_BACKEND_BUNDLE: ${{ vars.GP_BACKEND_BUNDLE }}
run: python download.py --target backend

- name: Close stale backend translation PRs
uses: actions/github-script@v8
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { data: pulls } = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open'
});
for (const pull of pulls) {
if (pull.title === "chore: update backend translations from Globalization Pipeline") {
await github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pull.number,
state: 'closed'
});
}
}

- name: Create Pull Request
id: create-pr
uses: peter-evans/create-pull-request@v8
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch-token: ${{ secrets.GITHUB_TOKEN }}
base: ${{ steps.resolve-branch.outputs.branch }}
commit-message: "chore: update backend translations from Globalization Pipeline [skip ci]"
title: "chore: update backend translations from Globalization Pipeline"
body: |
Automated PR to update backend locale files from IBM Globalization Pipeline.

This PR was automatically created by the `gp-download` workflow.
If no files changed, this PR will be empty and can be closed.
branch: translations/update-backend-gp
branch-suffix: timestamp
delete-branch: true
maintainer-can-modify: true
add-paths: src/backend/base/langflow/locales/*.json

- name: Enable auto-merge
if: steps.create-pr.outputs.pull-request-number != ''
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr merge ${{ steps.create-pr.outputs.pull-request-number }} --auto --squash \
--repo ${{ github.repository }}

- name: Report GP backend download failure
if: failure()
run: echo "::warning::GP backend translation download failed — backend translations may be out of date. Check the 'Download backend translations from GP' step above for details."
61 changes: 58 additions & 3 deletions .github/workflows/gp-upload.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@ on:
- "release-*"
paths:
- "src/frontend/src/locales/en.json"
- "src/backend/base/langflow/locales/en.json"
workflow_dispatch:

jobs:
upload:
upload-frontend:
runs-on: ubuntu-latest
name: Upload English strings to Globalization Pipeline
name: Upload frontend strings to GP
environment: GP-test
if: >-
github.event_name == 'workflow_dispatch' ||
contains(toJSON(github.event.commits.*.modified), 'src/frontend/src/locales/en.json')

steps:
- name: Checkout repository
Expand Down Expand Up @@ -53,4 +57,55 @@ jobs:
GP_ADMIN_PASSWORD: ${{ secrets.GP_ADMIN_PASSWORD }}
GP_INSTANCE: ${{ vars.GP_INSTANCE }}
GP_BUNDLE: ${{ vars.GP_BUNDLE }}
run: python upload_strings.py --source ../../src/frontend/src/locales/en.json
run: python upload.py --target frontend --source ../../src/frontend/src/locales/en.json

upload-backend:
runs-on: ubuntu-latest
name: Upload backend strings to GP
environment: GP-test
if: >-
github.actor != 'github-actions[bot]' && (
github.event_name == 'workflow_dispatch' ||
contains(toJSON(github.event.commits.*.modified), 'src/backend/base/langflow/locales/en.json')
)

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Check if this is the latest release branch
id: check-branch
run: |
LATEST=$(git ls-remote --heads https://github.com/${{ github.repository }} 'refs/heads/release-*' \
| awk '{print $2}' \
| sed 's|refs/heads/||' \
| grep -E '^release-[0-9]+\.[0-9]+\.[0-9]+$' \
| sort -V \
| tail -n 1)
CURRENT="${{ github.ref_name }}"
if [ "$CURRENT" != "$LATEST" ]; then
echo "skip=true" >> "$GITHUB_OUTPUT"
echo "::notice::Skipping upload — $CURRENT is not the latest release branch ($LATEST)"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi

- name: Set up Python
if: steps.check-branch.outputs.skip != 'true'
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install dependencies
if: steps.check-branch.outputs.skip != 'true'
run: pip install -r scripts/gp/requirements.txt

- name: Upload strings to GP
if: steps.check-branch.outputs.skip != 'true'
working-directory: scripts/gp
env:
GP_ADMIN_USER_ID: ${{ secrets.GP_ADMIN_USER_ID }}
GP_ADMIN_PASSWORD: ${{ secrets.GP_ADMIN_PASSWORD }}
GP_INSTANCE: ${{ vars.GP_INSTANCE }}
GP_BACKEND_BUNDLE: ${{ vars.GP_BACKEND_BUNDLE }}
run: python upload.py --target backend
101 changes: 101 additions & 0 deletions scripts/gp/bake_note_keys.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
"""Bake i18n_key into noteNodes in starter template JSON files.

For each noteNode in every starter project JSON:
- Compute the expected key: template_notes.{flow_key}.{sha256[:8]}
where the hash is derived from the noteNode's description field.
- If data.node.i18n_key already equals the expected key: leave it as-is.
- Otherwise (missing or stale after an edit): assign the expected key.

This means keys are content-addressed — they change automatically when the
description changes, stay stable when nodes are reordered, and never silently
collide when a note is deleted and a new one added at the same position.

en.json is managed exclusively by extract_backend_strings.py — run that after
baking to pick up any new or changed note keys.

Usage (from repo root, no virtualenv required):
python scripts/gp/bake_note_keys.py
python scripts/gp/bake_note_keys.py --dry-run # preview without writing
"""

from __future__ import annotations

import argparse
import hashlib
import json
import re
from pathlib import Path

REPO_ROOT = Path(__file__).parent.parent.parent
STARTER_PROJECTS_DIR = REPO_ROOT / "src/backend/base/langflow/initial_setup/starter_projects"

# NOTE: _safe_flow_key and _note_hash are intentionally kept inline (not imported from
# langflow.utils.i18n_keys) because this script is designed to run WITHOUT a virtualenv —
# the CI workflow calls it before the Python environment is set up. bake_note_keys.py
# only writes template_notes.{key} values that are read back verbatim by i18n.py at
# runtime, so a local drift here does NOT affect component-translation correctness.


def _safe_flow_key(name: str) -> str:
return re.sub(r"[^a-zA-Z0-9]+", "_", name).strip("_").lower()


def _note_hash(description: str) -> str:
return hashlib.sha256(description.encode()).hexdigest()[:8]


def _bake_file(path: Path, *, dry_run: bool) -> int:
"""Bake i18n_keys into a single template JSON file. Returns number of keys added/updated."""
with path.open(encoding="utf-8") as f:
data = json.load(f)

name = data.get("name") or path.stem
flow_key = _safe_flow_key(name)
nodes = data.get("data", {}).get("nodes", [])

keys_changed = 0

for node in nodes:
if node.get("type") != "noteNode":
continue
node_data = node["data"]["node"]
description = node_data.get("description", "")
expected = f"template_notes.{flow_key}.{_note_hash(description)}"

if node_data.get("i18n_key") == expected:
continue

action = "updating" if "i18n_key" in node_data else "assigning"
if not dry_run:
node_data["i18n_key"] = expected
print(f" + {path.name}: {action} {expected!r}")
keys_changed += 1

if keys_changed > 0 and not dry_run:
with path.open("w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
f.write("\n")

return keys_changed


def main() -> None:
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("--dry-run", action="store_true", help="Print changes without writing files")
args = parser.parse_args()

if args.dry_run:
print("DRY RUN — no files will be modified.\n")

total_changed = 0
for project_file in sorted(STARTER_PROJECTS_DIR.glob("*.json")):
total_changed += _bake_file(project_file, dry_run=args.dry_run)

template_count = len(list(STARTER_PROJECTS_DIR.glob("*.json")))
print(f"\nBaked {total_changed} i18n_key(s) across {template_count} templates.")
if total_changed > 0 and not args.dry_run:
print("Run extract_backend_strings.py to update en.json.")


if __name__ == "__main__":
main()
Loading
Loading