Compare commits

..

4 Commits

Author SHA1 Message Date
4493a41c50 trigger ci 2026-03-31 16:46:30 +08:00
26d0778da2 Merge branch 'main' into 3-31-vite-task-cache 2026-03-31 14:53:38 +08:00
bf470471f7 trigger ci 2026-03-31 11:17:32 +08:00
f833701a4a ci: enable vite task cache 2026-03-31 11:07:44 +08:00
9 changed files with 33 additions and 148 deletions

View File

@ -1,10 +1,11 @@
name: Setup Web Environment
description: A GitHub Action to set up the web environment using Vite+.
runs:
using: composite
steps:
- name: Setup Vite+
uses: voidzero-dev/setup-vp@20553a7a7429c429a74894104a2835d7fed28a72 # v1.3.0
uses: hyoban/setup-vp@96511aa421048609564ade4427c73d0078d4afc1 # v1.3.0
with:
node-version-file: .nvmrc
cache: true

View File

@ -106,12 +106,12 @@ jobs:
- name: Web tsslint
if: steps.changed-files.outputs.any_changed == 'true'
working-directory: ./web
run: vp run lint:tss
run: vp run lint:tss --cache
- name: Web type check
if: steps.changed-files.outputs.any_changed == 'true'
working-directory: ./web
run: vp run type-check
run: vp run type-check --cache
- name: Web dead code check
if: steps.changed-files.outputs.any_changed == 'true'

View File

@ -1,10 +1,10 @@
name: Translate i18n Files with Claude Code
# Note: claude-code-action doesn't support push events directly.
# Push events are bridged by trigger-i18n-sync.yml via repository_dispatch.
on:
repository_dispatch:
types: [i18n-sync]
push:
branches: [main]
paths:
- 'web/i18n/en-US/*.json'
workflow_dispatch:
inputs:
files:
@ -30,7 +30,7 @@ permissions:
concurrency:
group: translate-i18n-${{ github.event_name }}-${{ github.ref }}
cancel-in-progress: false
cancel-in-progress: ${{ github.event_name == 'push' }}
jobs:
translate:
@ -67,20 +67,19 @@ jobs:
}
" web/i18n-config/languages.ts | sed 's/[[:space:]]*$//')
if [ "${{ github.event_name }}" = "repository_dispatch" ]; then
BASE_SHA="${{ github.event.client_payload.base_sha }}"
HEAD_SHA="${{ github.event.client_payload.head_sha }}"
CHANGED_FILES="${{ github.event.client_payload.changed_files }}"
TARGET_LANGS="$DEFAULT_TARGET_LANGS"
SYNC_MODE="${{ github.event.client_payload.sync_mode || 'incremental' }}"
if [ -n "${{ github.event.client_payload.diff_base64 }}" ]; then
printf '%s' '${{ github.event.client_payload.diff_base64 }}' | base64 -d > /tmp/i18n-diff.txt
DIFF_AVAILABLE="true"
else
: > /tmp/i18n-diff.txt
DIFF_AVAILABLE="false"
if [ "${{ github.event_name }}" = "push" ]; then
BASE_SHA="${{ github.event.before }}"
if [ -z "$BASE_SHA" ] || [ "$BASE_SHA" = "0000000000000000000000000000000000000000" ]; then
BASE_SHA=$(git rev-parse HEAD~1 2>/dev/null || true)
fi
HEAD_SHA="${{ github.sha }}"
if [ -n "$BASE_SHA" ]; then
CHANGED_FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA" -- 'web/i18n/en-US/*.json' 2>/dev/null | sed -n 's@^.*/@@p' | sed 's/\.json$//' | tr '\n' ' ' | sed 's/[[:space:]]*$//')
else
CHANGED_FILES=$(find web/i18n/en-US -maxdepth 1 -type f -name '*.json' -print | sed -n 's@^.*/@@p' | sed 's/\.json$//' | sort | tr '\n' ' ' | sed 's/[[:space:]]*$//')
fi
TARGET_LANGS="$DEFAULT_TARGET_LANGS"
SYNC_MODE="incremental"
else
BASE_SHA=""
HEAD_SHA=$(git rev-parse HEAD)
@ -105,18 +104,6 @@ jobs:
else
CHANGED_FILES=""
fi
if [ "$SYNC_MODE" = "incremental" ] && [ -n "$BASE_SHA" ]; then
git diff "$BASE_SHA" "$HEAD_SHA" -- 'web/i18n/en-US/*.json' > /tmp/i18n-diff.txt 2>/dev/null || : > /tmp/i18n-diff.txt
else
: > /tmp/i18n-diff.txt
fi
if [ -s /tmp/i18n-diff.txt ]; then
DIFF_AVAILABLE="true"
else
DIFF_AVAILABLE="false"
fi
fi
FILE_ARGS=""
@ -136,7 +123,6 @@ jobs:
echo "CHANGED_FILES=$CHANGED_FILES"
echo "TARGET_LANGS=$TARGET_LANGS"
echo "SYNC_MODE=$SYNC_MODE"
echo "DIFF_AVAILABLE=$DIFF_AVAILABLE"
echo "FILE_ARGS=$FILE_ARGS"
echo "LANG_ARGS=$LANG_ARGS"
} >> "$GITHUB_OUTPUT"
@ -170,7 +156,6 @@ jobs:
- Head SHA: `${{ steps.context.outputs.HEAD_SHA }}`
- Scoped file args: `${{ steps.context.outputs.FILE_ARGS }}`
- Scoped language args: `${{ steps.context.outputs.LANG_ARGS }}`
- Full English diff available: `${{ steps.context.outputs.DIFF_AVAILABLE }}`
Tool rules:
- Use Read for repository files.
@ -188,9 +173,6 @@ jobs:
- Do not touch unrelated i18n files.
- Do not modify `${{ github.workspace }}/web/i18n/en-US/`.
3. Detect English changes per file.
- Treat the current English JSON files under `${{ github.workspace }}/web/i18n/en-US/` plus the scoped `i18n:check` result as the primary source of truth.
- Use `/tmp/i18n-diff.txt` only as supporting context to understand what changed between `Base SHA` and `Head SHA`.
- Never rely on diff alone when deciding final keys or values.
- Read the current English JSON file for each file in scope.
- If sync mode is `incremental` and `Base SHA` is not empty, run:
`git -C ${{ github.workspace }} show <Base SHA>:web/i18n/en-US/<file>.json`
@ -200,7 +182,7 @@ jobs:
- ADD: key only in current
- UPDATE: key exists in both and the English value changed
- DELETE: key only in previous
- If `/tmp/i18n-diff.txt` is available, read it before translating so wording changes are grounded in the full English patch, but resolve any ambiguity by trusting the actual English files and scoped checks.
- Do not rely on a truncated diff file.
4. Run a scoped pre-check before editing:
- `pnpm --dir ${{ github.workspace }}/web run i18n:check ${{ steps.context.outputs.FILE_ARGS }} ${{ steps.context.outputs.LANG_ARGS }}`
- Use this command as the source of truth for missing and extra keys inside the current scope.

View File

@ -1,81 +0,0 @@
name: Trigger i18n Sync on Push
on:
push:
branches: [main]
paths:
- 'web/i18n/en-US/*.json'
permissions:
contents: write
concurrency:
group: trigger-i18n-sync-${{ github.ref }}
cancel-in-progress: true
jobs:
trigger:
if: github.repository == 'langgenius/dify'
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- name: Detect changed files and generate full diff
id: detect
shell: bash
run: |
BASE_SHA="${{ github.event.before }}"
if [ -z "$BASE_SHA" ] || [ "$BASE_SHA" = "0000000000000000000000000000000000000000" ]; then
BASE_SHA=$(git rev-parse HEAD~1 2>/dev/null || true)
fi
HEAD_SHA="${{ github.sha }}"
if [ -n "$BASE_SHA" ]; then
CHANGED_FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA" -- 'web/i18n/en-US/*.json' 2>/dev/null | sed -n 's@^.*/@@p' | sed 's/\.json$//' | tr '\n' ' ' | sed 's/[[:space:]]*$//')
git diff "$BASE_SHA" "$HEAD_SHA" -- 'web/i18n/en-US/*.json' > /tmp/i18n-diff.txt 2>/dev/null || : > /tmp/i18n-diff.txt
else
CHANGED_FILES=$(find web/i18n/en-US -maxdepth 1 -type f -name '*.json' -print | sed -n 's@^.*/@@p' | sed 's/\.json$//' | sort | tr '\n' ' ' | sed 's/[[:space:]]*$//')
: > /tmp/i18n-diff.txt
fi
if [ -n "$CHANGED_FILES" ]; then
echo "has_changes=true" >> "$GITHUB_OUTPUT"
else
echo "has_changes=false" >> "$GITHUB_OUTPUT"
fi
echo "base_sha=$BASE_SHA" >> "$GITHUB_OUTPUT"
echo "head_sha=$HEAD_SHA" >> "$GITHUB_OUTPUT"
echo "changed_files=$CHANGED_FILES" >> "$GITHUB_OUTPUT"
- name: Trigger i18n sync workflow
if: steps.detect.outputs.has_changes == 'true'
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env:
BASE_SHA: ${{ steps.detect.outputs.base_sha }}
HEAD_SHA: ${{ steps.detect.outputs.head_sha }}
CHANGED_FILES: ${{ steps.detect.outputs.changed_files }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs')
const diffBase64 = fs.readFileSync('/tmp/i18n-diff.txt').toString('base64')
await github.rest.repos.createDispatchEvent({
owner: context.repo.owner,
repo: context.repo.repo,
event_type: 'i18n-sync',
client_payload: {
changed_files: process.env.CHANGED_FILES,
diff_base64: diffBase64,
sync_mode: 'incremental',
base_sha: process.env.BASE_SHA,
head_sha: process.env.HEAD_SHA,
},
})

View File

@ -272,28 +272,6 @@ describe('PromptEditor', () => {
expect(onFocus).toHaveBeenCalledTimes(1)
expect(onBlur).toHaveBeenCalledTimes(1)
})
it('should not call onBlur when blur target is var-search-input', () => {
const onBlur = vi.fn()
const onFocus = vi.fn()
render(
<PromptEditor
onFocus={onFocus}
onBlur={onBlur}
/>,
)
const blurHandler = mocks.commandHandlers.get(BLUR_COMMAND)
expect(blurHandler).toBeDefined()
const varInput = document.createElement('input')
varInput.classList.add('var-search-input')
blurHandler?.({ relatedTarget: varInput } as unknown as ReactFocusEvent<Element>)
expect(onBlur).not.toHaveBeenCalled()
})
})
// Prop typing guard for shortcut popup shape without any-casts.

View File

@ -45,8 +45,8 @@ const DSLExportConfirmModal = ({
<table className="radius-md w-full border-separate border-spacing-0 border border-divider-regular shadow-xs">
<thead className="system-xs-medium-uppercase text-text-tertiary">
<tr>
<td width={220} className="h-7 border-b border-r border-divider-regular pl-3">{t('env.export.name', { ns: 'workflow' })}</td>
<td className="h-7 border-b border-divider-regular pl-3">{t('env.export.value', { ns: 'workflow' })}</td>
<td width={220} className="h-7 border-b border-r border-divider-regular pl-3">NAME</td>
<td className="h-7 border-b border-divider-regular pl-3">VALUE</td>
</tr>
</thead>
<tbody>
@ -56,7 +56,7 @@ const DSLExportConfirmModal = ({
<div className="flex w-[200px] items-center gap-1">
<Env className="h-4 w-4 shrink-0 text-util-colors-violet-violet-600" />
<div className="truncate text-text-primary">{env.name}</div>
<div className="shrink-0 text-text-tertiary">{t('env.export.secret', { ns: 'workflow' })}</div>
<div className="shrink-0 text-text-tertiary">Secret</div>
<RiLock2Line className="h-3 w-3 shrink-0 text-text-tertiary" />
</div>
</td>

View File

@ -287,10 +287,7 @@
"env.export.checkbox": "Export secret values",
"env.export.export": "Export DSL with secret values ",
"env.export.ignore": "Export DSL",
"env.export.name": "Name",
"env.export.secret": "Secret",
"env.export.title": "Export Secret environment variables?",
"env.export.value": "Value",
"env.modal.description": "Description",
"env.modal.descriptionPlaceholder": "Describe the variable",
"env.modal.editTitle": "Edit Environment Variable",

View File

@ -4,6 +4,7 @@ import { codeInspectorPlugin } from 'code-inspector-plugin'
import { env } from './env'
const isDev = process.env.NODE_ENV === 'development'
const withMDX = createMDX()
const nextConfig: NextConfig = {

View File

@ -84,5 +84,12 @@ export default defineConfig(({ mode }) => {
reporter: isCI ? ['json', 'json-summary'] : ['text', 'json', 'json-summary'],
},
},
tasks: {
'type-check': {
command: 'tsc --noEmit',
input: [{ auto: true }, '!**/*.tsbuildinfo'],
},
},
}
})