Compare commits

...

202 Commits

Author SHA1 Message Date
Innei 4f1be9911a update 2025-12-25 21:58:23 +08:00
YuTengjing 41c0b3bab3 refactor: expose lobehub models 2025-12-25 21:48:30 +08:00
Innei 221bd6e5af chore: update i18n translations for multiple locales (#10973)
Update translations for ar, bg-BG, de-DE, es-ES, fa-IR, fr-FR, it-IT, ja-JP, ko-KR, nl-NL, pl-PL, pt-BR, ru-RU, tr-TR, vi-VN, zh-TW locales.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-25 21:28:18 +08:00
canisminor1990 3a59cf33e9 style: update agent back style 2025-12-25 21:24:27 +08:00
YuTengjing 92ca00eb85 refactor: remove some unused business code 2025-12-25 21:19:19 +08:00
YuTengjing 12fb04b88d refactor: move src/config/modelProviders to model-bank 2025-12-25 21:02:19 +08:00
YuTengjing d2a8b9ce02 refactor: remove lobehub configuration from LLM settings 2025-12-25 20:38:36 +08:00
YuTengjing d2cf3d1c33 fix: lint errors 2025-12-25 20:33:09 +08:00
canisminor1990 c004973b23 style: update token tag 2025-12-25 20:28:20 +08:00
YuTengjing 180ebfdf70 feat: Integrate bcryptjs for password verification in BetterAuth
- Added bcryptjs as a dependency for handling password verification.
- Updated the defineConfig function to support bcrypt password hashes migrated from Clerk.
- Implemented a new password verification method that checks for bcrypt hashes and falls back to BetterAuth's default verification.
2025-12-25 19:44:36 +08:00
YuTengjing 2e7076a9fd feat: Add turbopack configuration support to CustomNextConfig
- Introduced a new optional property `turbopack` in the CustomNextConfig interface.
- Updated the defineConfig function to merge turbopack settings from the provided config.
2025-12-25 19:26:11 +08:00
YuTengjing d86f9831ca refactor: extract common next config 2025-12-25 18:04:59 +08:00
Innei 89f89c7f83 fix(i18n): Translate plugin.ts locale to English (#10972)
Translate all plugin-related UI strings from Chinese to English following the microcopy guidelines:
- Use "Skill" as the standard term (not tool/plugin)
- Consistent terminology: Agent, Group, Library, Page, Memory, Workspace
- Clear, actionable language with concise phrasing
- Natural product-native English (avoid translationese)
- Preserved all placeholders for interpolation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-25 18:01:21 +08:00
Innei 0e89ce508a feat: Add i18n UI locales and improve tool types (#10964)
*  feat: Add i18n UI locales and improve tool types

- Add multiple UI locale files (ar, bg-BG, de-DE, es-ES, fa-IR, fr-FR, it-IT, ja-JP, ko-KR, nl-NL, pl-PL, pt-BR, ru-RU, tr-TR, vi-VN, zh-TW)
- Add getUILocaleAndResources utility with tests
- Update tool-related type definitions
- Use type-only imports for better tree-shaking

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* chore: update

* test: update siteName to use BRANDING_NAME and streamline translation mocks

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-25 17:37:35 +08:00
Shinji-Li c11d802d26 feat: add like action in community detail (#10971)
feat: add like action in community detail
2025-12-25 17:22:14 +08:00
canisminor1990 8630f61d61 style: update community style 2025-12-25 17:01:57 +08:00
canisminor1990 7803fc52c2 style: update community style 2025-12-25 17:01:56 +08:00
Shinji-Li 60eba456ed feat: support files upload in chat input (#10967)
* feat: add a custom drag upload way

* feat: add agent bulilder & page builder & group chat support upload files

* feat: use upload fileitem to show detail

* feat: support preview in chatinput files

* feat: add useUploadFiles hook to replace the repeat logic code
2025-12-25 16:56:21 +08:00
YuTengjing 9f1c79e9a7 Tj/refactor/businessify-3 (#10961) 2025-12-25 16:31:56 +08:00
Arvin Xu 15410d1a10 ♻️ refactor: clean page editor (#10966)
refactor and clean
2025-12-25 16:07:38 +08:00
Innei 568235c311 🐛 fix: Fix desktop test cases and refactor translations (#10956)
* 🐛 fix: fix desktop test cases and refactor translations

- Import translations from default locale instead of hardcoding
- Fix macOS menu test expectations to match actual translations
- Update I18nManager test to match implementation (fallbackLng: 'en')
- Support {{appName}} interpolation in test mocks

* 🐛 fix: add missing buildAndSetAppMenu calls in tests
2025-12-25 14:57:35 +08:00
Neko Ayaka 81d3e74aed feat(userMemories): added /api/dev/memory-user-memory/benchmark-locomo with feature flag gate, and webhook auth 2025-12-25 14:54:10 +08:00
Neko Ayaka 29c70b7b40 fix(memory-user-memory): incorrect format exported from LoCoMo 2025-12-25 14:54:10 +08:00
Neko Ayaka 3dfb18b3e2 refactor(userMemories): make CEPx4 + Ix1 parallel 2025-12-25 14:54:10 +08:00
CanisMinor c5fe456aec 🔨 chore: update compoents version (#10957)
chore: update deps
2025-12-25 12:52:31 +08:00
Innei b3520a2205 🐛 fix: Fix desktop test cases and refactor translations (#10955)
* 🐛 fix: fix desktop test cases and refactor translations

- Import translations from default locale instead of hardcoding
- Fix macOS menu test expectations to match actual translations
- Update I18nManager test to match implementation (fallbackLng: 'en')
- Support {{appName}} interpolation in test mocks

* 🐛 fix: add missing buildAndSetAppMenu calls in tests
2025-12-25 12:29:28 +08:00
Rene Wang 256309a6e4 fix: Type error 2025-12-25 11:47:39 +08:00
Arvin Xu 61b30310bc 🐛 fix: page agent editor (#10953)
* refactor page agent

* refactor page agent system prompt

* support inject page context in the agent runtime

* fix initial context injection

* support diff all toolbar
2025-12-25 11:38:15 +08:00
Rene Wang d43acc8e24 fix: Editor 2025-12-25 10:44:26 +08:00
Rene Wang f2dd3894c6 lint: Create consts for URLs 2025-12-25 10:30:00 +08:00
René Wang bda2d76fdf feat: Import from notion (#10948) 2025-12-24 23:16:57 +08:00
Shinji-Li 78ca5ebed5 🐛 fix: slove the mutate not work problem (#10947)
fix: slove the mutate not work problem
2025-12-24 22:42:50 +08:00
YuTengjing 0e49d11621 fix: maxDuration must use literal 2025-12-24 21:13:51 +08:00
Shinji-Li de949d19ad 🐛 fix add lost portal locals files (#10943)
fix: add lost portal locals files
2025-12-24 20:58:57 +08:00
Shinji-Li c224951340 feat: add always show tools render in createPlan & createDoc tools (#10937)
* feat: add always show tools render in createPlan & createDoc tools

* feat: add document protral can modify & jump to pages to modify it

* feat: add a warpper into portal render
2025-12-24 20:50:12 +08:00
Innei 1a4f4564f0 feat(desktop): macOS About menu should navigate to Settings About tab (#10942)
Changed the macOS app menu's "About" action from using the default Electron
about dialog to navigating to the Settings page's About tab.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-24 20:49:57 +08:00
Innei dc870c7635 ♻️ refactor: rename browser identifier from 'chat' to 'app' (#10940)
Rename the main browser identifier from 'chat' to 'app' to better represent its purpose as the main application window. Also update the initial path from '/agent' to '/' for the root route.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-24 20:43:11 +08:00
Innei e5f3a58056 ♻️ refactor: flatten i18n keys and extract hardcoded strings in desktop (#10939)
- Flatten all nested i18n objects to dot notation format (e.g. 'dialog.about.title')
- Add en-* locale fallback to use default TypeScript files
- Extract hardcoded Chinese strings in menu files to i18n keys
- Update 17 locale JSON files with flattened structure

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-24 20:29:19 +08:00
YuTengjing 187b5ab4b2 fix: remove useless config variable 2025-12-24 19:20:01 +08:00
YuTengjing bb39de4a24 chore: fix proxy.ts (#10938) 2025-12-24 17:58:16 +08:00
Innei d692a37e28 ♻️ refactor: i18n formatting optimization (#10929)
* ♻️ refactor: i18n formatting optimization

*  feat(i18n): update localization strings for clarity and consistency across chat, discover, and settings components

*  feat(i18n): update Chinese localization strings for improved clarity and consistency across various components, including chat, onboarding, and settings

* 🗑️ chore(i18n): remove outdated localization files for multiple languages to streamline the project and improve maintainability

*  feat(i18n): enhance localization loading logic to improve language handling and streamline imports for default and normalized locales

* 🐛 fix(i18n): restore English i18n keys that were incorrectly changed to Japanese characters

*  chore(i18n): Adjust Latin language locales for terminology consistency (#10933)

* This comprehensive update ensures all Latin language locales (de-DE, fr-FR, es-ES, it-IT, pt-BR, nl-NL, pl-PL) follow the microcopy style guide's terminology requirements.

**Total: 557 changes across 7 Latin locales**

1. **"Plugin" → "Skill"**
   - Fixed terminology inconsistency across all Latin languages
   - UI elements now consistently use "Skill" instead of localized equivalents
   - Includes both singular and plural forms: `plugin/Skill`, `plugins/Skills`

2. **"LobeChat" → "LobeHub"**
   - Updated brand name references to current branding

3. **"Agent" Terminology Consistency**
   - French: Fixed inconsistent "Assistant" → "Agent" usage in UI elements
   - Ensured consistent terminology across all languages

- **de-DE (German)**: 267 changes
- **fr-FR (French)**: 94 changes (including 7 Agent→Assistant fixes)
- **es-ES (Spanish)**: 39 changes
- **it-IT (Italian)**: 59 changes (including 18 plugin→skill fixes)
- **pt-BR (Portuguese)**: 58 changes
- **nl-NL (Dutch)**: 62 changes
- **pl-PL (Polish)**: 28 changes

- All 37 locale JSON files for each language (259 total files)
- Includes: auth.json, chat.json, common.json, discover.json, plugin.json, setting.json, etc.

1. **Fixed Terminology**: Following microcopy guide's fixed terminology rules
2. **Brand Consistency**: Changed all brand references to "LobeHub"
3. **Natural Localization**: Maintained natural language patterns while ensuring consistency
4. **User Experience**: Improved consistency across all Latin language interfaces

Two utility scripts for future locale maintenance:
- `scripts/adjust-latin-locales.py` - For common.json specific adjustments
- `scripts/adjust-latin-locales-full.py` - For comprehensive adjustments across all files

- All changes maintain backward compatibility
- No breaking changes to functionality
- JSON files validated and remain syntactically correct
- Changes reviewed against English base for consistency

---------

Co-authored-by: canisminor1990 <i@canisminor.cc>

*  feat(i18n): update welcome and group activity localization strings for improved clarity and consistency

*  chore(i18n): add ESLint directives to welcome localization file for improved code quality

* 🐛 fix(i18n): add missing footer translation keys for discover page

*  feat(i18n): restore footer translation keys for discover page

---------

Co-authored-by: canisminor1990 <i@canisminor.cc>
2025-12-24 17:54:42 +08:00
YuTengjing ca16409b39 🔨 chore: project structure businessify (#10930) 2025-12-24 17:52:22 +08:00
Rene Wang d0616ccebb feat: Use our own viewer 2025-12-24 17:44:38 +08:00
Rene Wang b9648deafe fix: Image preview 2025-12-24 17:44:31 +08:00
Rene Wang 7ee27c1531 fix: Restore placeholder 2025-12-24 17:44:24 +08:00
canisminor1990 89597a85bf style: update community footer and modal 2025-12-24 17:07:10 +08:00
Shinji-Li be4c17d4cc feat: buildin some tools should save into docs (#10935)
* feat: change the GTD & document protrol should show editor

* feat: when crawl website should save it into doc
2025-12-24 16:52:15 +08:00
canisminor1990 0f5ba3a6cd style: fix tool auto expand 2025-12-24 15:53:39 +08:00
canisminor1990 b65ffdcc15 style: fix some style issues 2025-12-24 15:38:35 +08:00
canisminor1990 2e37b65663 style: fix some style issues 2025-12-24 14:09:17 +08:00
Arvin Xu 1bb19027b3 test: fix some tests failed (#10927)
* fix tests

* fix tests

* fix tests

* improve title size

* fix tests

* fix messages

* fix messages
2025-12-24 13:47:06 +08:00
Neko c7c7d6f3c8 feat(memory-user-memory): support to extract memories from LoCoMo dataset (#10925) 2025-12-24 12:56:52 +08:00
Neko 9ac3ce7741 feat(memory-user-memory): support to load in memory, and extract from in-memory memory sources (#10924) 2025-12-24 12:56:52 +08:00
Neko a5dd785dca feat(memory-user-memory): added LoCoMo dataset loader & converter & exporter (#10923) 2025-12-24 12:56:52 +08:00
Neko 03342a76e3 ♻️ refactor(userMemories): added benchmark_locomo as source unify use the of source type (#10922)
refactor(userMemories): added benchmark_locomo as source unify use the of source type
2025-12-24 12:56:52 +08:00
Neko a6be1a7f75 refactor(userMemories): should use MemorySourceType (#10921) 2025-12-24 12:55:13 +08:00
Arvin Xu fbd0b666f0 🐛 fix: fix identity memory not working (#10916)
* update memory prompts

* fix memory issue

* update i18n

* update prompts and injector

* fix memory query issue

* remove fetchedAt

* fix identity memory issues

* fix lint

* fix topic messages query issues

* fix lint
2025-12-24 12:55:13 +08:00
CanisMinor 024aeb2e4e 💄 style: Update i18n microcopy (#10905)
* chore: update i18n

* chore: update i18n

* chore: update i18n

* chore: update i18n

* chore: update i18n

* chore: update i18n

* chore: update i18n

* chore: update i18n translations and placeholders across multiple components

Signed-off-by: Innei <tukon479@gmail.com>

* chore: update i18n translations for consistency in terminology across chat, onboarding, and settings components

Signed-off-by: Innei <tukon479@gmail.com>

* chore: update i18n translations to replace 'assistant' with 'agent' and ensure consistency across all components

Signed-off-by: Innei <tukon479@gmail.com>

* chore: update model descriptions in locales for clarity and accuracy

Signed-off-by: Innei <tukon479@gmail.com>

* feat: extract hard code string

Signed-off-by: Innei <tukon479@gmail.com>

* feat: enhance Chinese localization with new proxy and sync settings, update dialog messages for version checks and OAuth authorization

Signed-off-by: Innei <tukon479@gmail.com>

* chore: flatten

* chore: standardize localization keys by flattening nested structures across multiple languages

Signed-off-by: Innei <tukon479@gmail.com>

* chore: refine i18n documentation by consolidating key naming conventions and workflow guidelines for translation management

Signed-off-by: Innei <tukon479@gmail.com>

* chore: update i18n

* feat: add chat title localization for improved user experience in Chinese

Signed-off-by: Innei <tukon479@gmail.com>

---------

Signed-off-by: Innei <tukon479@gmail.com>
Co-authored-by: Innei <tukon479@gmail.com>
2025-12-24 12:55:12 +08:00
René Wang 1f3531f8f5 feat: Better CMDK (#10915)
* lint: Remove unused console.log

* lint: Clean up console.log

* lint: Clean up console.log

* lint: Clean up console.log

* fix: Page creaetion

* feat: Add more CMDK commands

* feat: Create team in the CMDK

* feat: Context aware commands

* feat: Ask AI menu

* feat: SHow agent list in CMDK

* feat: Lobe AI

* feat: Adjust text

* feat: Add email entry
2025-12-24 12:55:11 +08:00
Arvin Xu e05375f796 feat: support notebook tool (#10902)
* add notebook builtin tool

* document init workflow

* gtd support plan mode

* add notebook tools
2025-12-24 12:55:09 +08:00
Shinji-Li c6a6e246d8 feat: community support like and follow (#10913)
* feat: add user follow and like agent/mcp

* feat: update market sdk& api call back
2025-12-24 12:54:47 +08:00
Innei 1a99f3f37e ️ perf(tooltip): group tooltip to optimize tooltip performance (#10906)
 perf: integrate TooltipGroup component across various UI components

- Added TooltipGroup to enhance tooltip management in Header, ProviderList, ModelList, UserAgentCard, and LikeButton components.
- Updated imports to include TooltipGroup in relevant files for consistent tooltip behavior.
- Refactored existing tooltip implementations to utilize TooltipGroup for better organization and performance.

Signed-off-by: Innei <tukon479@gmail.com>
2025-12-24 12:54:47 +08:00
Innei a34c1113eb 🐛 fix: remove openapi pkg patch file (#10910)
🔧 chore: remove deprecated patch for @swagger-api/apidom-reference from package.json and delete associated patch file

Signed-off-by: Innei <tukon479@gmail.com>
2025-12-24 12:54:47 +08:00
Innei 2558b47822 🐛 fix(desktop): add safe top edge for message container (#10908)
fix(desktop): add safe top edge for message container

Signed-off-by: Innei <tukon479@gmail.com>
2025-12-24 12:54:47 +08:00
Neko 4e65f11ab5 refactor(memory-user-memory,userMemories): split chat topic related operations into dedicated pipelines sub-route (#10907) 2025-12-24 12:54:46 +08:00
Shinji-Li 3183189cc2 feat: add home page create group builder button (#10904)
feat: add group builder inhome page use sender
2025-12-24 12:54:46 +08:00
Innei 83fa92268d ️perf: reduce back to home render time (#10890)
*  feat: update DesktopHome layout and routing

* Upgraded @lobehub/ui to version 3.4.2.
* Enhanced DesktopHome layout with conditional rendering of PageTitle based on route.
* Refactored home layout to manage visibility and activation state.
* Updated desktop router configuration to streamline home page handling.

Signed-off-by: Innei <tukon479@gmail.com>

* refactor: simplify layout visibility handling in home component

* Removed pointerEvents and visibility styles based on route condition.
* Streamlined layout rendering logic for improved performance.

Signed-off-by: Innei <tukon479@gmail.com>

---------

Signed-off-by: Innei <tukon479@gmail.com>
2025-12-24 12:54:46 +08:00
Innei ca373f643e 🔨 chore: update patch file to try fix build error (#10900)
🔧 chore: update apidom-reference patch and clean up binary parser code

Signed-off-by: Innei <tukon479@gmail.com>
2025-12-24 12:54:46 +08:00
Innei 6d7dce798f 🐛 fix: bump charts 3.0.4 to fix import es path (#10898)
🔧 chore: update @lobehub/charts dependency to version 3.0.4 in package.json

Signed-off-by: Innei <tukon479@gmail.com>
2025-12-24 12:54:46 +08:00
Innei e22fd2761c 🔨 chore: bump @lobehub/charts (#10897)
chore: update @lobehub/charts dependency to version 3.0.2 in package.json

Signed-off-by: Innei <tukon479@gmail.com>
2025-12-24 12:54:46 +08:00
Innei e51225baa8 test: fix desktop test case (#10894)
test(logger): enhance logger tests with mocked environment variables

* Added mock for getDesktopEnv to simulate various NODE_ENV and DEBUG_VERBOSE states.
* Updated logger tests to utilize the mocked environment for consistent behavior across different log levels.
* Ensured that logger methods correctly handle production and development environments.

Signed-off-by: Innei <tukon479@gmail.com>
2025-12-24 12:54:46 +08:00
Shinji-Li b3fbffe428 🐛 fix: slove swr mutate not work in Cache Provider (#10895)
fix: slove swr mutate not work in Cache Provider
2025-12-24 12:54:46 +08:00
Innei 95c6840162 fix(import): fix lobehub ui es import path (#10893)
chore: update package dependencies and import paths

* Updated @lobehub/ui from version 3.4.2 to 3.4.4 in package.json.
* Adjusted import paths for components from '@lobehub/ui/es/' to include '.mjs' extension where necessary.
* Refactored imports for motion library to use 'motion/react-m' instead of 'motion/react'.
* Cleaned up import statements in various components for consistency.

Signed-off-by: Innei <tukon479@gmail.com>
2025-12-24 12:54:46 +08:00
Shinji-Li 613a404bf5 feat: topic message swr cache (#10886)
feat: add topic message swr cache
2025-12-24 12:54:46 +08:00
canisminor1990 d9de7a547e style: fix some style issues 2025-12-24 12:54:46 +08:00
René Wang ba6a5475bc feat: Remove docs_ prefix from URL (#10888)
* feat: Remove page filter

* feat: Replace medium with youtube

* feat: Remove `docs_` prefix from URL

* fix: TS error
2025-12-24 12:54:46 +08:00
Innei c29c02bb23 🐛 fix(desktop): prevent window resize when onboarding (#10887)
 feat: add window resizing and sizing functionality

* Implemented IPC methods for setting window size and resizability.
* Updated Browser and BrowserManager classes to handle new window settings.
* Integrated window settings in DesktopOnboarding component.
* Added new types for window size and resizability in electron-client-ipc.

Signed-off-by: Innei <tukon479@gmail.com>
2025-12-24 12:54:45 +08:00
canisminor1990 1b0b49cc1a style: fix some style issues 2025-12-24 12:54:45 +08:00
Shinji-Li bc3f3e2a07 feat: support swr local cache (#10884)
* feat: add localstorage cache in swr provider

* feat: add use fetch topic into cache

* feat: add homepage recents api cache

* feat: add group chat initial cache

* docs: update the hint
2025-12-24 12:54:45 +08:00
Arvin Xu 0c5a41f896 feat: support export and import topic JSON (#10885)
* support export topic json

*  feat: support import and export topic data

* update config
2025-12-24 12:54:45 +08:00
YuTengjing c927d5ec86 chore: sync some changes from cloud (#10882) 2025-12-24 12:54:45 +08:00
René Wang c1be517fd6 feat: Improve CMDK (#10877)
* fix: Search more of a speific topic

* refac: Warp CommandItem

* fix: Type error

* fix: AddButton cannot expand

* style: Back button position

* refac: Use context instead of hook

* style: Add hint

* fix: Add missing translation

* lint: Remove unused varibles
2025-12-24 12:54:44 +08:00
canisminor1990 49b97df50c style: update AgentCouncil actions 2025-12-24 12:54:44 +08:00
Shinji-Li 5a79cb9116 🐛 fix: slove when first call thread, not show ai chat message (#10878)
fix: slove when first call thread, not show ai chat message
2025-12-24 12:54:44 +08:00
canisminor1990 a9cda5b46e style: fix antd modal padding 2025-12-24 12:54:44 +08:00
canisminor1990 45630015e2 style: update AgentCouncil style 2025-12-24 12:54:44 +08:00
canisminor1990 33e00b5a77 style: fix some antd v6 style issues 2025-12-24 12:54:44 +08:00
Innei 86dd27b0e1 chore: update references from react-layout-kit to @lobehub/ui for Flexbox and Center components in documentation and rules
Signed-off-by: Innei <tukon479@gmail.com>
2025-12-24 12:54:44 +08:00
YuTengjing 3c8973b9ba fix: improve tooltip hover behavior in ModelSelect component 2025-12-24 12:54:43 +08:00
canisminor1990 cedcbae038 style: remove react layout kit 2025-12-24 12:54:43 +08:00
canisminor1990 36327a7432 style: remove some memo 2025-12-24 12:54:43 +08:00
arvinxx 7dd30ebb98 🐛 fix: fix thread not working issue 2025-12-24 12:54:43 +08:00
arvinxx c632b22d97 fix agent session group not working 2025-12-24 12:54:43 +08:00
canisminor1990 53e8088f74 style: update tool style 2025-12-24 12:54:43 +08:00
canisminor1990 79274f6dee style: update tools style 2025-12-24 12:54:43 +08:00
Innei 672bcf7740 feat: wrap ConversationArea and ModelSwitchPanel in TooltipGroup for enhanced UI
Signed-off-by: Innei <tukon479@gmail.com>
2025-12-24 12:54:42 +08:00
arvinxx 4f98c1199d fix home send message 2025-12-24 12:54:42 +08:00
canisminor1990 511d6acef5 chore: update antd v6 2025-12-24 12:54:42 +08:00
arvinxx 2e6fd07c19 🌐 style: update i18n 2025-12-24 12:54:42 +08:00
arvinxx 728ce7344d 🚨 chore: fix lint 2025-12-24 12:54:42 +08:00
Shinji-Li 0a39a71245 🔧 chore: update some code 2025-12-24 12:54:42 +08:00
René Wang d2bd8a6d84 feat: support CMD K 2025-12-24 12:54:41 +08:00
arvinxx 685a6cd5a5 feat: server implement 2025-12-24 12:54:41 +08:00
YuTengjing 34d059ffae ♻️ refactor: refactor implement 2025-12-24 12:54:41 +08:00
Innei ac9363784f feat: desktop feature 2025-12-24 12:54:41 +08:00
arvinxx d5ce1442b3 feat: user memory 2025-12-24 12:54:41 +08:00
Shinji-Li ede0ed6d37 feat: agent builder 2025-12-24 12:54:41 +08:00
canisminor1990 83e689f342 💄 style: refactor UI in features 2025-12-24 12:54:40 +08:00
arvinxx 9c46c6ed89 feat: implement server data feature 2025-12-24 12:54:40 +08:00
canisminor1990 e44a82bc14 🌐 chore: add i18n 2025-12-24 12:54:40 +08:00
Innei 849ee3daa3 ♻️ refactor: refactor with electron 2025-12-24 12:54:40 +08:00
canisminor1990 1693fc5666 💄 style: update ui 2025-12-24 12:54:40 +08:00
arvinxx 96c1379e9c 🔧 chore: update config 2025-12-24 12:54:40 +08:00
arvinxx d735e2c810 feat: agent builder and group builder 2025-12-24 12:54:39 +08:00
arvinxx 4ddb491a74 ♻️ refactor: clean code 2025-12-24 12:54:39 +08:00
arvinxx 81d33a6c97 feat: onboarding ui 2025-12-24 12:54:39 +08:00
arvinxx ad14222371 💄 style: rebranding chat ui 2025-12-24 12:54:39 +08:00
Shinji-Li e3c945423f feat: agent builder 2025-12-24 12:54:39 +08:00
arvinxx 91bbbf5cb0 ♻️ refactor: refactor service 2025-12-24 12:54:39 +08:00
arvinxx 78d07c0504 feat: app ui page 2025-12-24 12:54:39 +08:00
arvinxx e3fa62e73a ♻️ refactor: refactor hooks 2025-12-24 12:54:39 +08:00
arvinxx 1b32d3a95d tests: refactor tests 2025-12-24 12:54:38 +08:00
Neko 49ffcb5c06 feat: user memory 2025-12-24 12:54:38 +08:00
arvinxx 6bf4546c92 ♻️ refactor: tools ui 2025-12-24 12:54:38 +08:00
arvinxx 9786d6462a feat: file search feature 2025-12-24 12:54:38 +08:00
arvinxx 9e47c33e9f feat: add db and schema feature 2025-12-24 12:54:38 +08:00
Neko fdae83ca2d feat: add memory implement 2025-12-24 12:54:38 +08:00
Innei 6ff8efacb3 🔧 chore: clean code 2025-12-24 12:54:38 +08:00
arvinxx 1940914e8b feat: code-interpreter tool 2025-12-24 12:54:38 +08:00
Shinji-Li c931909eda feat: code-interpreter tool 2025-12-24 12:54:38 +08:00
Shinji-Li baa29c882b feat: code-interpreter tool 2025-12-24 12:54:37 +08:00
canisminor1990 13ca81bafa feat: rebranding total UI of app 2025-12-24 12:54:37 +08:00
canisminor1990 436d9e5e8d ♻️ refactor: refactor ui and layout 2025-12-24 12:54:37 +08:00
Innei ffd7d23d5c ♻️ refactor: clean desktop relative code 2025-12-24 12:54:37 +08:00
René Wang 492d3ccbf6 feat: page and knowledge base 2025-12-24 12:54:37 +08:00
YuTengjing 5e59388317 feat: user onboarding 2025-12-24 12:54:37 +08:00
arvinxx c305889ac4 feat: add user memory 2025-12-24 12:54:37 +08:00
Innei 1848d279d9 ♻️ refactor: refactor with es-toolkit 2025-12-24 12:54:36 +08:00
Innei a69221f4f8 ♻️ refactor: refactor local-system 2025-12-24 12:54:36 +08:00
Shinji-Li f638b97517 feat: implement agent builder 2025-12-24 12:54:36 +08:00
arvinxx 2255a7cc51 feat: implement builtin agents packages 2025-12-24 12:54:36 +08:00
Neko 7f94ef1478 feat: implement memories package 2025-12-24 12:54:36 +08:00
Innei 27f101f51e ♻️ refactor: refactor implement for desktop 2025-12-24 12:54:36 +08:00
arvinxx 26e73cc438 ♻️ refactor: add builtin tools 2025-12-24 12:54:36 +08:00
arvinxx 2da0691d4e 🔧 chore: update basic config 2025-12-24 12:54:35 +08:00
Innei 10e048c9c5 feat: refactor desktop implement with brand new 2.0 2025-12-24 12:54:35 +08:00
lobehubbot b5720434e4 📝 docs(bot): Auto sync agents & plugin to readme 2025-12-23 11:12:01 +00:00
semantic-release-bot cec3754c48 🔖 chore(release): v2.0.0-next.176 [skip ci]
## [Version&nbsp;2.0.0-next.176](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.175...v2.0.0-next.176)
<sup>Released on **2025-12-23**</sup>

####  Features

- **misc**: Mobile native better auth support.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's improved

* **misc**: Mobile native better auth support, closes [#10871](https://github.com/lobehub/lobe-chat/issues/10871) ([8c42a93](https://github.com/lobehub/lobe-chat/commit/8c42a93))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2025-12-23 11:10:42 +00:00
Arvin Xu 9be0893dba 👷 build: improve document db schema (#10892)
* add document db schema update

* update migration sql

* update migration sql
2025-12-23 18:54:48 +08:00
Rdmclin2 8c42a934b3 feat: mobile native better auth support (#10871)
* feat: mobile native better auth support

* chore: add android assetlinks

* chore: add android assetlinks

* chore: add expo fingerpoint

* chore: add relation

* chore: add android origin hash

* chore: update passkey table

* chore: optimize version

* chore: remove as any

* fix: sql not exits problem

* fix: passkey statement

* fix:  passkey origin null

* chore: remove strict peer dependencies

* fix: test case

* chore: remove local passkey origin
2025-12-23 15:19:42 +08:00
lobehubbot cf02912965 📝 docs(bot): Auto sync agents & plugin to readme 2025-12-21 13:54:52 +00:00
semantic-release-bot af96f577ec 🔖 chore(release): v2.0.0-next.175 [skip ci]
## [Version&nbsp;2.0.0-next.175](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.174...v2.0.0-next.175)
<sup>Released on **2025-12-21**</sup>

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2025-12-21 13:53:37 +00:00
Arvin Xu 50b042f73e 👷 build: add session group in agents table (#10868)
add session group
2025-12-21 21:38:20 +08:00
lobehubbot 8abff4c450 📝 docs(bot): Auto sync agents & plugin to readme 2025-12-20 12:35:56 +00:00
semantic-release-bot 93d2bb995f 🔖 chore(release): v2.0.0-next.174 [skip ci]
## [Version&nbsp;2.0.0-next.174](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.173...v2.0.0-next.174)
<sup>Released on **2025-12-20**</sup>

#### ♻ Code Refactoring

- **misc**: Refactor database schema.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### Code refactoring

* **misc**: Refactor database schema, closes [#10860](https://github.com/lobehub/lobe-chat/issues/10860) ([5c489bc](https://github.com/lobehub/lobe-chat/commit/5c489bc))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2025-12-20 12:34:34 +00:00
Arvin Xu 5c489bc971 ♻️ refactor: refactor database schema (#10860)
* update data schema

* update data schema
2025-12-20 20:20:07 +08:00
Arvin Xu 5cc9141b52 🔨 chore: update config (#10857)
chore update config
2025-12-19 23:13:22 +08:00
Arvin Xu 3c4ef8a837 🔨 chore: update agent coding rule (#10856)
update agent coding rule
2025-12-19 23:05:15 +08:00
Jiyuan Zheng 5ed88d7947 📝 docs: Update development guide links in README and README.zh-CN (#10806)
* 📝 docs: Update development guide links in README and README.zh-CN

* 📝 docs(zh-CN): Fix typo
2025-12-16 16:38:16 +08:00
lobehubbot 486e14efd9 📝 docs(bot): Auto sync agents & plugin to readme 2025-12-16 06:31:08 +00:00
semantic-release-bot 11e065cd05 🔖 chore(release): v2.0.0-next.173 [skip ci]
## [Version&nbsp;2.0.0-next.173](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.172...v2.0.0-next.173)
<sup>Released on **2025-12-16**</sup>

#### 🐛 Bug Fixes

- **misc**: Request to gpt5 series should not with `top_p`, temperature when reasoning effort  is not none.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's fixed

* **misc**: Request to gpt5 series should not with `top_p`, temperature when reasoning effort  is not none, closes [#10800](https://github.com/lobehub/lobe-chat/issues/10800) ([b4ad470](https://github.com/lobehub/lobe-chat/commit/b4ad470))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2025-12-16 06:29:49 +00:00
Rylan Cai b4ad47054a 🐛 fix: request to gpt5 series should not with top_p, temperature when reasoning effort is not none (#10800)
* 🐛 fix: gpt5.2 reasoning effort should not with top_p, temperature

*  test: adjust tests to align behaviors
2025-12-16 14:14:35 +08:00
lobehubbot 216e49ac7c 📝 docs(bot): Auto sync agents & plugin to readme 2025-12-16 02:18:08 +00:00
Arvin Xu 01cd222d5e 🐛 fix fix Knowledge Base select list (#10798)
fix kb list
2025-12-16 10:03:08 +08:00
lobehubbot a32e0cc7b9 📝 docs(bot): Auto sync agents & plugin to readme 2025-12-15 18:10:05 +00:00
semantic-release-bot d11e9d5dde 🔖 chore(release): v2.0.0-next.172 [skip ci]
## [Version&nbsp;2.0.0-next.172](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.171...v2.0.0-next.172)
<sup>Released on **2025-12-15**</sup>

#### 💄 Styles

- **misc**: Update i18n.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### Styles

* **misc**: Update i18n, closes [#10759](https://github.com/lobehub/lobe-chat/issues/10759) ([24cae77](https://github.com/lobehub/lobe-chat/commit/24cae77))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2025-12-15 18:08:54 +00:00
LobeHub Bot 24cae772ef 🤖 style: update i18n (#10759)
💄 style: update i18n

Co-authored-by: canisminor1990 <17870709+canisminor1990@users.noreply.github.com>
2025-12-16 01:54:30 +08:00
lobehubbot 3230f13817 📝 docs(bot): Auto sync agents & plugin to readme 2025-12-14 17:22:36 +00:00
semantic-release-bot c3ca76293c 🔖 chore(release): v2.0.0-next.171 [skip ci]
## [Version&nbsp;2.0.0-next.171](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.170...v2.0.0-next.171)
<sup>Released on **2025-12-14**</sup>

#### 💄 Styles

- **misc**: Update GPT-5.2 models.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### Styles

* **misc**: Update GPT-5.2 models, closes [#10749](https://github.com/lobehub/lobe-chat/issues/10749) ([0446127](https://github.com/lobehub/lobe-chat/commit/0446127))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2025-12-14 17:21:10 +00:00
Arvin Xu 81e56d462a ️ perf: add more sql to improve performance (#10777)
* Update sql

* fix user tests
2025-12-15 01:06:34 +08:00
sxjeru 0446127910 💄 style: Update GPT-5.2 models (#10749)
*  feat: 添加 GPT-5.2 和 GPT-5.2 Pro 模型及其推理努力滑块

*  feat: 添加 GPT-5.2 和 GPT-5.2 Pro 模型,更新 GPT-5.2 推理努力滑块的标签

* 🔨 chore: 移除 GPT-5.2 和 GPT-5.2 Pro 模型的推理努力参数及相关组件

*  feat: 更新模型设置,添加 gpt5_1ReasoningEffort 参数
2025-12-12 23:28:51 +08:00
YuTengjing 79b2afda70 revert: remove after() from image router to avoid resource waste (#10757) 2025-12-12 23:07:05 +08:00
YuTengjing 0287239975 🔨 chore: optimize not await async call (#10756) 2025-12-12 22:58:09 +08:00
lobehubbot 2da6cac673 📝 docs(bot): Auto sync agents & plugin to readme 2025-12-12 12:25:26 +00:00
semantic-release-bot c46bd6e49a 🔖 chore(release): v2.0.0-next.170 [skip ci]
## [Version&nbsp;2.0.0-next.170](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.169...v2.0.0-next.170)
<sup>Released on **2025-12-12**</sup>

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2025-12-12 12:24:16 +00:00
René Wang ec3aa6ba3b ️ perf(database): optimize document queries with indexes and field exclusion (#10740)
* ️ perf(database): optimize document queries with indexes and field exclusion

- Add database indexes for source_type and compound query optimization
- Exclude large JSONB fields (content, pages, editorData) in list queries
- Improve queryDocuments performance for better list view rendering

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* feat: Add migration

* ️ perf(database): missing user_id and user_memory_id index

* refac: Use select

* fix: migration

* fix: Test error

* Update sql

* feat(userMemories): added captured_at column

* fix: not null default now

* fix: not null default now

* Update sql

* Update sql

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Neko Ayaka <neko@ayaka.moe>
Co-authored-by: arvinxx <arvinx@foxmail.com>
2025-12-12 20:09:08 +08:00
lobehubbot 0cb8bc1179 📝 docs(bot): Auto sync agents & plugin to readme 2025-12-12 04:39:50 +00:00
semantic-release-bot 5cb69336b2 🔖 chore(release): v2.0.0-next.169 [skip ci]
## [Version&nbsp;2.0.0-next.169](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.168...v2.0.0-next.169)
<sup>Released on **2025-12-12**</sup>

#### 🐛 Bug Fixes

- **misc**: Fix CVE errors.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's fixed

* **misc**: Fix CVE errors, closes [#10748](https://github.com/lobehub/lobe-chat/issues/10748) ([6591f3c](https://github.com/lobehub/lobe-chat/commit/6591f3c))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2025-12-12 04:38:41 +00:00
LobeHub Bot 84a6e711b8 🌐 chore: translate non-English comments to English in file-loaders (#10746)
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-12 12:25:17 +08:00
Pleasure1234 6591f3c4ef 🐛 fix: fix CVE errors (#10748)
fix: fix cve errors
2025-12-12 12:23:10 +08:00
lobehubbot 157d9accbc 📝 docs(bot): Auto sync agents & plugin to readme 2025-12-12 03:44:09 +00:00
semantic-release-bot 7cfc9a28e4 🔖 chore(release): v2.0.0-next.168 [skip ci]
## [Version&nbsp;2.0.0-next.168](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.167...v2.0.0-next.168)
<sup>Released on **2025-12-12**</sup>

#### 🐛 Bug Fixes

- **misc**: Slove market oidc error.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's fixed

* **misc**: Slove market oidc error, closes [#10715](https://github.com/lobehub/lobe-chat/issues/10715) ([108d2a7](https://github.com/lobehub/lobe-chat/commit/108d2a7))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2025-12-12 03:42:53 +00:00
Shinji-Li 108d2a72a5 🐛 fix: slove market oidc error (#10715)
fix: slove oidc error
2025-12-12 11:27:59 +08:00
lobehubbot 05ca7b51be 📝 docs(bot): Auto sync agents & plugin to readme 2025-12-11 10:31:14 +00:00
semantic-release-bot 2923bc676e 🔖 chore(release): v2.0.0-next.167 [skip ci]
## [Version&nbsp;2.0.0-next.167](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.166...v2.0.0-next.167)
<sup>Released on **2025-12-11**</sup>

####  Features

- **misc**: Add Replicate image provider.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's improved

* **misc**: Add Replicate image provider ([542f4d9](https://github.com/lobehub/lobe-chat/commit/542f4d9))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2025-12-11 10:29:50 +00:00
YuTengjing a44224132a 🔨 chore: fix ci (#10735) 2025-12-11 17:53:54 +08:00
YuTengjing 458cbf4d5c 🔨 chore: track user last active time (#10733) 2025-12-11 17:14:25 +08:00
Oriol Rius 542f4d97dd feat: Add Replicate image provider
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-11 15:43:00 +08:00
lobehubbot 1c187063cd 📝 docs(bot): Auto sync agents & plugin to readme 2025-12-09 09:33:36 +00:00
semantic-release-bot 82424887dd 🔖 chore(release): v2.0.0-next.166 [skip ci]
## [Version&nbsp;2.0.0-next.166](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.165...v2.0.0-next.166)
<sup>Released on **2025-12-09**</sup>

#### 🐛 Bug Fixes

- **Dockerfile**: Electron main typing pkg.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's fixed

* **Dockerfile**: Electron main typing pkg, closes [#10693](https://github.com/lobehub/lobe-chat/issues/10693) ([f3357b0](https://github.com/lobehub/lobe-chat/commit/f3357b0))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2025-12-09 09:32:21 +00:00
Innei f3357b0b46 🔧 fix(Dockerfile): electron main typing pkg (#10693) 2025-12-09 17:17:31 +08:00
lobehubbot a8822940b3 📝 docs(bot): Auto sync agents & plugin to readme 2025-12-09 07:18:25 +00:00
semantic-release-bot f312661166 🔖 chore(release): v2.0.0-next.165 [skip ci]
## [Version&nbsp;2.0.0-next.165](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.164...v2.0.0-next.165)
<sup>Released on **2025-12-09**</sup>

#### ♻ Code Refactoring

- **electron-main**: Client ipc decorate.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### Code refactoring

* **electron-main**: Client ipc decorate, closes [#10679](https://github.com/lobehub/lobe-chat/issues/10679) ([f74befa](https://github.com/lobehub/lobe-chat/commit/f74befa))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2025-12-09 07:17:05 +00:00
Innei f74befadc9 ♻️ refactor(electron-main): client ipc decorate (#10679)
* refactor: client ipc

* refactor: server ipc

refactor: update IPC method names for consistency

Signed-off-by: Innei <tukon479@gmail.com>

fix: cast IPC return type to DesktopIpcServices for type safety

Signed-off-by: Innei <tukon479@gmail.com>

chore: add new workspace for desktop application in package.json

Signed-off-by: Innei <tukon479@gmail.com>

fix: export FileMetadata interface for improved accessibility

Signed-off-by: Innei <tukon479@gmail.com>

refactor: unify IPC mocking across test files for consistency

Signed-off-by: Innei <tukon479@gmail.com>

feat: enhance type-safe IPC flow with context propagation and service registry

- Introduced `getIpcContext()` and `runWithIpcContext()` for improved context management in IPC handlers.
- Updated `BrowserWindowsCtr` methods to utilize the new context handling.
- Added `McpInstallCtr` to the IPC constructors registry.
- Enhanced README with details on the new type-safe IPC features.

Signed-off-by: Innei <tukon479@gmail.com>

refactor: enhance IPC method registration for improved type safety

- Updated `registerMethod` in `IpcHandler` and `IpcService` to accept variable argument types, enhancing flexibility in method signatures.
- Simplified the `ExtractMethodSignature` type to support multiple arguments.

Signed-off-by: Innei <tukon479@gmail.com>

chore: add global type definitions and refactor import statements

- Introduced a new global type definition file to support Vite client imports.
- Refactored import statements in `App.ts` and `App.test.ts` to remove unnecessary type casting for `import.meta.glob`, improving code clarity.

Signed-off-by: Innei <tukon479@gmail.com>

* refactor: make groupName in BrowserWindowsCtr readonly for better encapsulation

Signed-off-by: Innei <tukon479@gmail.com>

* refactor: update IPC method registration and usage for improved type safety and consistency

- Replaced `@ipcClientEvent` with `@IpcMethod()` in various controllers to standardize IPC method definitions.
- Enhanced the usage of `ensureElectronIpc()` for type-safe IPC calls in service layers.
- Updated `BrowserWindowsCtr` and `NotificationCtr` to utilize the new IPC method structure, improving encapsulation and clarity.
- Refactored service methods to eliminate manual string concatenation for IPC event names, ensuring better maintainability.

Signed-off-by: Innei <tukon479@gmail.com>

---------

Signed-off-by: Innei <tukon479@gmail.com>
2025-12-09 15:01:18 +08:00
Neko a775f6544c 🔨 chore(deps): remove @types/ioredis as ioredis now provides types by default (#10654)
chore(deps): remove @types/ioredis as ioredis now provides types by default
2025-12-09 10:34:00 +08:00
lobehubbot d9c4d672ca 📝 docs(bot): Auto sync agents & plugin to readme 2025-12-08 10:33:09 +00:00
semantic-release-bot 8645a6db16 🔖 chore(release): v2.0.0-next.164 [skip ci]
## [Version&nbsp;2.0.0-next.164](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.163...v2.0.0-next.164)
<sup>Released on **2025-12-08**</sup>

#### 💄 Styles

- **profile**: Add mobile responsive layout and signup improvements.
- **misc**: Update link handling in PlanTag component to use react-router-dom.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### Styles

* **profile**: Add mobile responsive layout and signup improvements, closes [#10669](https://github.com/lobehub/lobe-chat/issues/10669) ([1afd471](https://github.com/lobehub/lobe-chat/commit/1afd471))
* **misc**: Update link handling in PlanTag component to use react-router-dom, closes [#10673](https://github.com/lobehub/lobe-chat/issues/10673) ([3aceeb6](https://github.com/lobehub/lobe-chat/commit/3aceeb6))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2025-12-08 10:31:51 +00:00
YuTengjing 3aceeb6d94 💄 style: update link handling in PlanTag component to use react-router-dom (#10673) 2025-12-08 18:13:31 +08:00
YuTengjing 1afd4710e7 💄 style(profile): add mobile responsive layout and signup improvements (#10669) 2025-12-08 18:05:07 +08:00
lobehubbot b09361fbce 📝 docs(bot): Auto sync agents & plugin to readme 2025-12-06 14:55:13 +00:00
semantic-release-bot ecdda9d452 🔖 chore(release): v2.0.0-next.163 [skip ci]
## [Version&nbsp;2.0.0-next.163](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.162...v2.0.0-next.163)
<sup>Released on **2025-12-06**</sup>

#### 🐛 Bug Fixes

- **misc**: Add smooth scroll to top on 'More' button click in Title component.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's fixed

* **misc**: Add smooth scroll to top on 'More' button click in Title component, closes [#10178](https://github.com/lobehub/lobe-chat/issues/10178) ([5ad4f0c](https://github.com/lobehub/lobe-chat/commit/5ad4f0c))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2025-12-06 14:53:55 +00:00
bbbugg 5ad4f0c3ad 🐛 fix: add smooth scroll to top on 'More' button click in Title component (#10178)
* 💄 style: implement smooth scroll to top functionality in Nav and Title components

* fix: update link handling in Title component for improved navigation

* fix: enhance pagination scrolling behavior for mobile responsiveness
2025-12-06 22:39:05 +08:00
4610 changed files with 397496 additions and 268487 deletions
+10 -4
View File
@@ -5,20 +5,26 @@ alwaysApply: false
# Database Migrations Guide
## Step1: Generate migrations:
## Step1: Generate migrations
```bash
bun run db:generate
```
this step will generate or update the following files:
this step will generate following files:
- packages/database/migrations/0046_meaningless_file_name.sql
- packages/database/migrations/0046_meaningless_file_name.sql
and update the following files:
- packages/database/migrations/0046_xxx.sql
- packages/database/migrations/meta/\_journal.json
- packages/database/src/core/migrations.json
- docs/development/database-schema.dbml
## Step2: optimize the migration sql fileName
the migration sql file name is randomly generated, we need to optimize the file name to make it more readable and meaningful. For example, `0046_xxx.sql` -> `0046_better_auth.sql`
the migration sql file name is randomly generated, we need to optimize the file name to make it more readable and meaningful. For example, `0046_meaningless_file_name.sql` -> `0046_user_add_avatar_column.sql`
## Step3: Defensive Programming - Use Idempotent Clauses
@@ -36,13 +36,13 @@ LobeChat 桌面端基于 Electron 框架构建,采用主进程-渲染进程架
1. **创建控制器 (Controller)**
- 位置:`apps/desktop/src/main/controllers/`
- 示例:创建 `NewFeatureCtr.ts`
- 规范:按 `_template.ts` 模板格式实现
- 注册:在 `apps/desktop/src/main/controllers/index.ts` 导出
- 需继承 `ControllerModule`,并设置 `static readonly groupName`(例如 `static override readonly groupName = 'newFeature';`
- 按 `_template.ts` 模板格式实现,并在 `apps/desktop/src/main/controllers/registry.ts` 的 `controllerIpcConstructors`(或 `controllerServerIpcConstructors`)中注册,保证类型推导与自动装配
2. **定义 IPC 事件处理器**
- 使用 `@ipcClientEvent('eventName')` 装饰器注册事件处理函数
- 处理函数应接收前端传递的参数并返回结果
- 处理可能的错误情况
- 使用 `@IpcMethod()` 装饰器暴露渲染进程可访问的通道,或使用 `@IpcServerMethod()` 声明仅供 Next.js 服务器调用的 IPC
- 通道名称基于 `groupName.methodName` 自动生成,不再手动拼接字符串
- 处理函数可通过 `getIpcContext()` 获取 `sender`、`event` 等上下文信息,并按照需要返回结构化结果
3. **实现业务逻辑**
- 可能需要调用 Electron API 或 Node.js 原生模块
@@ -60,15 +60,17 @@ LobeChat 桌面端基于 Electron 框架构建,采用主进程-渲染进程架
1. **创建服务层**
- 位置:`src/services/electron/`
- 添加服务方法调用 IPC
- 使用 `dispatch` 或 `invoke` 函数
- 使用 `ensureElectronIpc()` 生成的类型安全代理,避免手动拼通道名称
```typescript
// src/services/electron/newFeatureService.ts
import { dispatch } from '@lobechat/electron-client-ipc';
import { NewFeatureParams } from 'types';
import { ensureElectronIpc } from '@/utils/electron/ipc';
import type { NewFeatureParams } from '@lobechat/electron-client-ipc';
const ipc = ensureElectronIpc();
export const newFeatureService = async (params: NewFeatureParams) => {
return dispatch('newFeatureEventName', params);
return ipc.newFeature.doSomething(params);
};
```
@@ -118,36 +120,31 @@ LobeChat 桌面端基于 Electron 框架构建,采用主进程-渲染进程架
```typescript
// apps/desktop/src/main/controllers/NotificationCtr.ts
import { BrowserWindow, Notification } from 'electron';
import { ipcClientEvent } from 'electron-client-ipc';
import { Notification } from 'electron';
import { ControllerModule, IpcMethod } from '@/controllers';
import type {
DesktopNotificationResult,
ShowDesktopNotificationParams,
} from '@lobechat/electron-client-ipc';
interface ShowNotificationParams {
title: string;
body: string;
}
export default class NotificationCtr extends ControllerModule {
static override readonly groupName = 'notification';
@IpcMethod()
async showDesktopNotification(
params: ShowDesktopNotificationParams,
): Promise<DesktopNotificationResult> {
if (!Notification.isSupported()) {
return { error: 'Notifications not supported', success: false };
}
export class NotificationCtr {
@ipcClientEvent('showNotification')
async handleShowNotification({ title, body }: ShowNotificationParams) {
try {
if (!Notification.isSupported()) {
return { success: false, error: 'Notifications not supported' };
}
const notification = new Notification({
title,
body,
});
const notification = new Notification({ body: params.body, title: params.title });
notification.show();
return { success: true };
} catch (error) {
console.error('Failed to show notification:', error);
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
};
console.error('[NotificationCtr] Failed to show notification:', error);
return { error: error instanceof Error ? error.message : 'Unknown error', success: false };
}
}
}
@@ -51,15 +51,15 @@ alwaysApply: false
* 导入在步骤 2 中定义的 IPC 参数类型。
* 添加一个新的 `async` 方法,方法名通常与 Action 名称对应 (例如: `renameLocalFile`)。
* 方法接收 `params` (符合 IPC 参数类型)。
* 使用从 `@lobechat/electron-client-ipc` 导入的 `dispatch` (或 `invoke`) 函数,调用与 Manifest 中 `name` 字段匹配的 IPC 事件名称,并将 `params` 传递过去。
* 通过 `ensureElectronIpc()` 获取 IPC 代理 (`const ipc = ensureElectronIpc();`),调用与 Manifest 中 `name` 字段匹配的链式方法,并将 `params` 传递过去。
* 定义方法的返回类型,通常是 `Promise<{ success: boolean; error?: string }>`,与后端 Controller 返回的结构一致。
5. **实现后端逻辑 (Controller / IPC Handler):**
* **文件:** `apps/desktop/src/main/controllers/[ToolName]Ctr.ts` (例如: `apps/desktop/src/main/controllers/LocalFileCtr.ts`)
* **操作:**
* 导入 Node.js 相关模块 (`fs`, `path` 等) 和 IPC 相关依赖 (`ipcClientEvent`, 参数类型等)。
* 导入 Node.js 相关模块 (`fs`, `path` 等) 和 IPC 相关依赖 (`ControllerModule`, `IpcMethod`/`IpcServerMethod`、参数类型等)。
* 添加一个新的 `async` 方法,方法名通常以 `handle` 开头 (例如: `handleRenameFile`)。
* 使用 `@ipcClientEvent('yourApiName')` 装饰器将此方法注册为对应 IPC 事件的处理器,确保 `'yourApiName'` 与 Manifest 中的 `name` Service 层调用的事件名称一致。
* 使用 `@IpcMethod()` 或 `@IpcServerMethod()` 装饰器将此方法注册为对应 IPC 事件的处理器,确保方法名与 Manifest 中的 `name` 以及 Service 层的链式调用一致。
* 方法的参数应解构自 Service 层传递过来的对象,类型与步骤 2 中定义的 IPC 参数类型匹配。
* 实现核心业务逻辑:
* 进行必要的输入验证。
+58 -68
View File
@@ -149,50 +149,52 @@ export const createMainWindow = () => {
1. **在主进程中注册 IPC 处理器**
```typescript
// BrowserWindowsCtr.ts
@ipcClientEvent('minimizeWindow')
handleMinimizeWindow() {
const focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow) {
focusedWindow.minimize();
}
return { success: true };
}
// apps/desktop/src/main/controllers/BrowserWindowsCtr.ts
import { BrowserWindow } from 'electron';
import { ControllerModule, IpcMethod } from '@/controllers';
@ipcClientEvent('maximizeWindow')
handleMaximizeWindow() {
const focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow) {
if (focusedWindow.isMaximized()) {
focusedWindow.restore();
} else {
focusedWindow.maximize();
}
}
return { success: true };
}
export default class BrowserWindowsCtr extends ControllerModule {
static override readonly groupName = 'windows';
@ipcClientEvent('closeWindow')
handleCloseWindow() {
const focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow) {
focusedWindow.close();
@IpcMethod()
minimizeWindow() {
const focusedWindow = BrowserWindow.getFocusedWindow();
focusedWindow?.minimize();
return { success: true };
}
@IpcMethod()
maximizeWindow() {
const focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow?.isMaximized()) focusedWindow.restore();
else focusedWindow?.maximize();
return { success: true };
}
@IpcMethod()
closeWindow() {
BrowserWindow.getFocusedWindow()?.close();
return { success: true };
}
return { success: true };
}
```
- `@IpcMethod()` 根据控制器的 `groupName` 自动将方法映射为 `windows.minimizeWindow` 形式的通道名称。
- 控制器需继承 `ControllerModule`,并在 `controllers/registry.ts` 中通过 `controllerIpcConstructors` 注册,便于类型生成。
2. **在渲染进程中调用**
```typescript
// src/services/electron/windowService.ts
import { dispatch } from '@lobechat/electron-client-ipc';
import { ensureElectronIpc } from '@/utils/electron/ipc';
const ipc = ensureElectronIpc();
export const windowService = {
minimize: () => dispatch('minimizeWindow'),
maximize: () => dispatch('maximizeWindow'),
close: () => dispatch('closeWindow'),
minimize: () => ipc.windows.minimizeWindow(),
maximize: () => ipc.windows.maximizeWindow(),
close: () => ipc.windows.closeWindow(),
};
```
- `ensureElectronIpc()` 会基于 `DesktopIpcServices` 运行时生成 Proxy,并通过 `window.electronAPI.invoke` 与主进程通信;不再直接使用 `dispatch`。
### 5. 自定义窗口控制 (无边框窗口)
@@ -252,45 +254,33 @@ export const createMainWindow = () => {
```typescript
// apps/desktop/src/main/controllers/BrowserWindowsCtr.ts
import type { OpenSettingsWindowOptions } from '@lobechat/electron-client-ipc';
import { ControllerModule, IpcMethod } from '@/controllers';
export default class BrowserWindowsCtr extends ControllerModule {
static override readonly groupName = 'windows';
@IpcMethod()
async openSettingsWindow(options?: string | OpenSettingsWindowOptions) {
const normalizedOptions =
typeof options === 'string' || options === undefined
? { tab: typeof options === 'string' ? options : undefined }
: options;
const mainWindow = this.app.browserManager.getMainWindow();
const query = new URLSearchParams();
if (normalizedOptions.tab) query.set('active', normalizedOptions.tab);
if (normalizedOptions.searchParams) {
for (const [key, value] of Object.entries(normalizedOptions.searchParams)) {
if (value) query.set(key, value);
}
}
const fullPath = `/settings${query.size ? `?${query.toString()}` : ''}`;
await mainWindow.loadUrl(fullPath);
mainWindow.show();
@ipcClientEvent('openSettings')
handleOpenSettings() {
// 检查设置窗口是否已经存在
if (this.settingsWindow && !this.settingsWindow.isDestroyed()) {
// 如果窗口已存在,将其置于前台
this.settingsWindow.focus();
return { success: true };
}
// 创建新窗口
this.settingsWindow = new BrowserWindow({
width: 800,
height: 600,
title: 'Settings',
parent: this.mainWindow, // 设置父窗口,使其成为模态窗口
modal: true,
webPreferences: {
preload: path.join(__dirname, '../preload/index.js'),
contextIsolation: true,
nodeIntegration: false,
},
});
// 加载设置页面
if (isDev) {
this.settingsWindow.loadURL('http://localhost:3000/settings');
} else {
this.settingsWindow.loadFile(
path.join(__dirname, '../../renderer/index.html'),
{ hash: 'settings' }
);
}
// 监听窗口关闭事件
this.settingsWindow.on('closed', () => {
this.settingsWindow = null;
});
return { success: true };
}
```
+33 -17
View File
@@ -1,8 +1,9 @@
---
description:
description:
globs: src/database/schemas/*
alwaysApply: false
---
# Drizzle ORM Schema Style Guide for lobe-chat
This document outlines the conventions and best practices for defining PostgreSQL Drizzle ORM schemas within the lobe-chat project.
@@ -16,7 +17,8 @@ This document outlines the conventions and best practices for defining PostgreSQ
## Helper Functions
Commonly used column definitions, especially for timestamps, are centralized in [src/database/schemas/_helpers.ts](mdc:src/database/schemas/_helpers.ts):
Commonly used column definitions, especially for timestamps, are centralized in [src/database/schemas/\_helpers.ts](mdc:src/database/schemas/_helpers.ts):
- `timestamptz(name: string)`: Creates a timestamp column with timezone
- `createdAt()`, `updatedAt()`, `accessedAt()`: Helper functions for standard timestamp columns
- `timestamps`: An object `{ createdAt, updatedAt, accessedAt }` for easy inclusion in table definitions
@@ -29,6 +31,7 @@ Commonly used column definitions, especially for timestamps, are centralized in
## Column Definitions
### Primary Keys (PKs)
- Typically `text('id')` (or `varchar('id')` for some OIDC tables)
- Often use `.$defaultFn(() => idGenerator('table_name'))` for automatic ID generation with meaningful prefixes
- **ID Prefix Purpose**: Makes it easy for users and developers to distinguish different entity types at a glance
@@ -36,24 +39,29 @@ Commonly used column definitions, especially for timestamps, are centralized in
- Composite PKs are defined using `primaryKey({ columns: [t.colA, t.colB] })`
### Foreign Keys (FKs)
- Defined using `.references(() => otherTable.id, { onDelete: 'cascade' | 'set null' | 'no action' })`
- FK columns are usually named `related_table_singular_name_id` (e.g., `user_id` references `users.id`)
- Most tables include a `user_id` column referencing `users.id` with `onDelete: 'cascade'`
### Timestamps
- Consistently use the `...timestamps` spread from [_helpers.ts](mdc:src/database/schemas/_helpers.ts) for `created_at`, `updated_at`, and `accessed_at` columns
- Consistently use the `...timestamps` spread from [\_helpers.ts](mdc:src/database/schemas/_helpers.ts) for `created_at`, `updated_at`, and `accessed_at` columns
### Default Values
- `.$defaultFn(() => expression)` for dynamic defaults (e.g., `idGenerator()`, `randomSlug()`)
- `.default(staticValue)` for static defaults (e.g., `boolean('enabled').default(true)`)
### Indexes
- Defined in the table's second argument: `pgTable('name', {...columns}, (t) => ({ indexName: indexType().on(...) }))`
- Use `uniqueIndex()` for unique constraints and `index()` for non-unique indexes
- Naming pattern: `table_name_column(s)_idx` or `table_name_column(s)_unique`
- Many tables feature a `clientId: text('client_id')` column, often part of a composite unique index with `user_id`
### Data Types
- Common types: `text`, `varchar`, `jsonb`, `boolean`, `integer`, `uuid`, `pgTable`
- For `jsonb` fields, specify the TypeScript type using `.$type<MyType>()` for better type safety
@@ -97,9 +105,7 @@ export const agents = pgTable(
...timestamps,
},
// return array instead of object, the object style is deprecated
(t) => [
uniqueIndex('client_id_user_id_unique').on(t.clientId, t.userId),
],
(t) => [uniqueIndex('client_id_user_id_unique').on(t.clientId, t.userId)],
);
export const insertAgentSchema = createInsertSchema(agents);
@@ -110,6 +116,7 @@ export type AgentItem = typeof agents.$inferSelect;
## Common Patterns
### 1. userId + clientId Pattern (Legacy)
Some existing tables include both fields for different purposes:
```typescript
@@ -129,6 +136,7 @@ clientIdUnique: uniqueIndex('agents_client_id_user_id_unique').on(t.clientId, t.
- **Note**: This pattern is being phased out for new features to simplify the schema
### 2. Junction Tables (Many-to-Many Relationships)
Use composite primary keys for relationship tables:
```typescript
@@ -136,21 +144,26 @@ Use composite primary keys for relationship tables:
export const agentsKnowledgeBases = pgTable(
'agents_knowledge_bases',
{
agentId: text('agent_id').references(() => agents.id, { onDelete: 'cascade' }).notNull(),
knowledgeBaseId: text('knowledge_base_id').references(() => knowledgeBases.id, { onDelete: 'cascade' }).notNull(),
userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }).notNull(),
agentId: text('agent_id')
.references(() => agents.id, { onDelete: 'cascade' })
.notNull(),
knowledgeBaseId: text('knowledge_base_id')
.references(() => knowledgeBases.id, { onDelete: 'cascade' })
.notNull(),
userId: text('user_id')
.references(() => users.id, { onDelete: 'cascade' })
.notNull(),
enabled: boolean('enabled').default(true),
...timestamps,
},
(t) => [
primaryKey({ columns: [t.agentId, t.knowledgeBaseId] }),
],
(t) => [primaryKey({ columns: [t.agentId, t.knowledgeBaseId] })],
);
```
**Pattern**: `{entity1}Id` + `{entity2}Id` as composite PK, plus `userId` for ownership
### 3. OIDC Tables Special Patterns
OIDC tables use `varchar` IDs instead of `text` with custom generators:
```typescript
@@ -166,6 +179,7 @@ export const oidcAuthorizationCodes = pgTable('oidc_authorization_codes', {
**Reason**: OIDC standards expect specific ID formats and lengths
### 4. File Processing with Async Tasks
File-related tables reference async task IDs for background processing:
```typescript
@@ -173,17 +187,21 @@ File-related tables reference async task IDs for background processing:
export const files = pgTable('files', {
// ... other fields
chunkTaskId: uuid('chunk_task_id').references(() => asyncTasks.id, { onDelete: 'set null' }),
embeddingTaskId: uuid('embedding_task_id').references(() => asyncTasks.id, { onDelete: 'set null' }),
embeddingTaskId: uuid('embedding_task_id').references(() => asyncTasks.id, {
onDelete: 'set null',
}),
// ...
});
```
**Purpose**:
**Purpose**:
- Track file chunking progress (breaking files into smaller pieces)
- Track embedding generation progress (converting text to vectors)
- Allow querying task status and handling failures
### 5. Slug Pattern (Legacy)
Some entities include auto-generated slugs - this is legacy code:
```typescript
@@ -195,8 +213,6 @@ slug: varchar('slug', { length: 100 })
slugUserIdUnique: uniqueIndex('slug_user_id_unique').on(t.slug, t.userId),
```
**Current usage**: Only used to identify default agents/sessions (legacy pattern)
**Future refactor**: Will likely be replaced with `isDefault: boolean()` field
**Note**: Avoid using slugs for new features - prefer explicit boolean flags for status tracking
**Current usage**: Only used to identify default agents/sessions (legacy pattern) **Future refactor**: Will likely be replaced with `isDefault: boolean()` field **Note**: Avoid using slugs for new features - prefer explicit boolean flags for status tracking
By following these guidelines, maintain consistency, type safety, and maintainability across database schema definitions.
-35
View File
@@ -1,35 +0,0 @@
---
description: Explain how group chat works in LobeHub (Multi-agent orchestratoin)
globs:
alwaysApply: false
---
This rule explains how group chat (multi-agent orchestration) works. Not confused with session group, which is a organization method to manage session.
## Key points
- A supervisor will devide who and how will speak next
- Each agent will speak just like in single chat (if was asked to speak)
- Not coufused with session group
## Related Files
- src/store/chat/slices/message/supervisor.ts
- src/store/chat/slices/aiChat/actions/generateAIGroupChat.ts
- src/prompts/groupChat/index.ts (All prompts here)
## Snippets
```tsx
// Detect whether in group chat
const isGroupSession = useSessionStore(sessionSelectors.isCurrentSessionGroupSession);
// Member actions
const addAgentsToGroup = useChatGroupStore((s) => s.addAgentsToGroup);
const removeAgentFromGroup = useChatGroupStore((s) => s.removeAgentFromGroup);
const persistReorder = useChatGroupStore((s) => s.reorderGroupMembers);
// Get group info
const groupConfig = useChatGroupStore(chatGroupSelectors.currentGroupConfig);
const currentGroupMemebers = useSessionStore(sessionSelectors.currentGroupAgents);
```
+161
View File
@@ -0,0 +1,161 @@
---
alwaysApply: false
---
# 如何添加新的快捷键:开发者指南
本指南将带您一步步地向 LobeChat 添加一个新的快捷键功能。我们将通过一个完整示例,演示从定义到实现的整个过程。
## 示例场景
假设我们要添加一个新的快捷键功能:**快速清空聊天记录**,快捷键为 `Mod+Shift+Backspace`。
## 步骤 1:更新快捷键常量定义
首先,在 `src/types/hotkey.ts` 中更新 `HotkeyEnum`
```typescript
export const HotkeyEnum = {
// 已有的快捷键...
AddUserMessage: 'addUserMessage',
EditMessage: 'editMessage',
// 新增快捷键
ClearChat: 'clearChat', // 添加这一行
// 其他已有快捷键...
} as const;
```
## 步骤 2:注册默认快捷键
在 `src/const/hotkeys.ts` 中添加快捷键的默认配置:
```typescript
import { KeyMapEnum as Key, combineKeys } from '@lobehub/ui';
// ...现有代码
export const HOTKEYS_REGISTRATION: HotkeyRegistration = [
// 现有的快捷键配置...
// 添加新的快捷键配置
{
group: HotkeyGroupEnum.Conversation, // 归类到会话操作组
id: HotkeyEnum.ClearChat,
keys: combineKeys([Key.Mod, Key.Shift, Key.Backspace]),
scopes: [HotkeyScopeEnum.Chat], // 在聊天作用域下生效
},
// 其他现有快捷键...
];
```
## 步骤 3:添加国际化翻译
在 `src/locales/default/hotkey.ts` 中添加对应的文本描述:
```typescript
import { HotkeyI18nTranslations } from '@/types/hotkey';
const hotkey: HotkeyI18nTranslations = {
// 现有翻译...
// 添加新快捷键的翻译
clearChat: {
desc: '清空当前会话的所有消息记录',
title: '清空聊天记录',
},
// 其他现有翻译...
};
export default hotkey;
```
如需支持其他语言,还需要在相应的语言文件中添加对应翻译。
## 步骤 4:创建并注册快捷键 Hook
在 `src/hooks/useHotkeys/chatScope.ts` 中添加新的 Hook
```typescript
export const useClearChatHotkey = () => {
const clearMessages = useChatStore((s) => s.clearMessages);
const { t } = useTranslation();
return useHotkeyById(HotkeyEnum.ClearChat, showConfirm);
};
// 注册聚合
export const useRegisterChatHotkeys = () => {
const { enableScope, disableScope } = useHotkeysContext();
useOpenChatSettingsHotkey();
// ...其他快捷键
useClearChatHotkey();
useEffect(() => {
enableScope(HotkeyScopeEnum.Chat);
return () => disableScope(HotkeyScopeEnum.Chat);
}, []);
return null;
};
```
## 步骤 5:给相应 UI 元素添加 Tooltip 提示(可选)
如果有对应的 UI 按钮,可以添加快捷键提示:
```tsx
import { DeleteOutlined } from '@ant-design/icons';
import { Tooltip } from '@lobehub/ui';
import { Button } from 'antd';
import { useTranslation } from 'react-i18next';
import { useUserStore } from '@/store/user';
import { settingsSelectors } from '@/store/user/selectors';
import { HotkeyEnum } from '@/types/hotkey';
const ClearChatButton = () => {
const { t } = useTranslation(['hotkey', 'chat']);
const clearChatHotkey = useUserStore(settingsSelectors.getHotkeyById(HotkeyEnum.ClearChat));
// 获取清空聊天的方法
const clearMessages = useChatStore((s) => s.clearMessages);
return (
<Tooltip hotkey={clearChatHotkey} title={t('clearChat.title', { ns: 'hotkey' })}>
<Button icon={<DeleteOutlined />} onClick={clearMessages} />
</Tooltip>
);
};
```
## 步骤 6:测试新快捷键
1. 启动开发服务器
2. 打开聊天页面
3. 按下设置的快捷键组合(`Cmd+Shift+Backspace` 或 `Ctrl+Shift+Backspace`
4. 确认功能正常工作
5. 检查快捷键设置面板中是否正确显示了新快捷键
## 最佳实践
1. **作用域考虑**:根据功能决定快捷键应属于全局作用域还是聊天作用域
2. **分组合理**:将快捷键放在合适的功能组中(System/Layout/Conversation
3. **冲突检查**:确保新快捷键不会与现有系统、浏览器或应用快捷键冲突
4. **平台适配**:使用 `Key.Mod` 而非硬编码 `Ctrl` 或 `Cmd`,以适配不同平台
5. **提供清晰描述**:为快捷键添加明确的标题和描述,帮助用户理解功能
按照以上步骤,您可以轻松地向系统添加新的快捷键功能,提升用户体验。如有特殊需求,如桌面专属快捷键,可以通过 `isDesktop` 标记进行区分处理。
## 常见问题排查
- **快捷键未生效**:检查作用域是否正确,以及是否在 RegisterHotkeys 中调用了对应的 hook
- **快捷键设置面板未显示**:确认在 HOTKEYS_REGISTRATION 中正确配置了快捷键
- **快捷键冲突**:在 HotkeyInput 组件中可以检测到冲突,用户会看到警告
- **功能在某些页面失效**:确认是否注册在了正确的作用域,以及相关页面是否激活了该作用域
通过这些步骤,您可以确保新添加的快捷键功能稳定、可靠且用户友好。
+49 -148
View File
@@ -2,181 +2,82 @@
globs: *.tsx
alwaysApply: false
---
# LobeChat Internationalization Guide
## Key Points
- Default language: Chinese (zh-CN) as the source language
- Supported languages: 18 languages including English, Japanese, Korean, Arabic, etc.
- Framework: react-i18next with Next.js app router
- Translation automation: @lobehub/i18n-cli for automatic translation, config file: .i18nrc.js
- Never manually modify any json file. You can only modify files in `default` folder
- Default language: Chinese (zh-CN), Framework: react-i18next
- **Only edit files in `src/locales/default/`** - Never edit JSON files in `locales/`
- Run `pnpm i18n` to generate all translations (or manually translate zh-CN/en-US for dev preview)
## Directory Structure
## Key Naming Convention
```
src/locales/
├── default/ # Source language files (zh-CN)
│ ├── index.ts # Namespace exports
│ ├── common.ts # Common translations
│ ├── chat.ts # Chat-related translations
│ ├── setting.ts # Settings translations
│ └── ... # Other namespace files
└── resources.ts # Type definitions and language configuration
locales/ # Translation files
├── en-US/ # English translations
│ ├── common.json # Common translations
│ ├── chat.json # Chat translations
│ ├── setting.json # Settings translations
│ └── ... # Other namespace JSON files
├── ja-JP/ # Japanese translations
│ ├── common.json
│ ├── chat.json
│ └── ...
└── ... # Other language folders
```
## Workflow for Adding New Translations
### 1. Adding New Translation Keys
Step 1: Add translation keys in the corresponding namespace files under src/locales/default directory
**Flat keys with dot notation** (not nested objects):
```typescript
// Example: src/locales/default/common.ts
// ✅ Correct
export default {
// ... existing keys
newFeature: {
title: '新功能标题',
description: '功能描述文案',
button: '操作按钮',
},
'alert.cloud.action': '立即体验',
'clientDB.error.desc': '数据库初始化遇到问题',
'sync.actions.sync': '立即同步',
'sync.status.ready': '已连接',
};
// ❌ Avoid: Nested objects
export default {
alert: { cloud: { action: '...' } },
};
```
Step 2: If creating a new namespace, export it in src/locales/default/index.ts
**Naming patterns:** `{feature}.{context}.{action|status}`
- `clientDB.modal.title` - Feature + context + property
- `sync.actions.sync` - Feature + group + action
- `sync.status.ready` - Feature + group + status
**Parameters:** Use `{{variableName}}` syntax
```typescript
'alert.cloud.desc': '我们提供 {{credit}} 额度积分',
```
**Avoid key conflicts:** Don't use both a leaf key and its parent path
```typescript
import newNamespace from './newNamespace';
// ❌ Conflict: clientDB.solve exists as both leaf and parent
'clientDB.solve': '自助解决',
'clientDB.solve.backup.title': '数据备份',
const resources = {
// ... existing namespaces
newNamespace,
} as const;
// ✅ Solution: Use different suffixes
'clientDB.solve.action': '自助解决',
'clientDB.solve.backup.title': '数据备份',
```
### 2. Translation Process
## Workflow
Development mode:
1. Add keys to `src/locales/default/{namespace}.ts`
2. Export new namespace in `src/locales/default/index.ts`
3. For dev preview: manually translate `locales/zh-CN/{namespace}.json` and `locales/en-US/{namespace}.json`
4. Run `pnpm i18n` to generate all languages (CI handles this automatically)
Generally, you don't need to help me run the automatic translation tool as it takes a long time. I'll run it myself when needed. However, to see immediate results, you still need to translate `locales/zh-CN/namespace.json` first, no need to translate other languages.
Production mode:
```bash
# Generate translations for all languages
npm run i18n
```
## Usage in Components
### Basic Usage
## Usage
```tsx
import { useTranslation } from 'react-i18next';
const MyComponent = () => {
const { t } = useTranslation('common');
return (
<div>
<h1>{t('newFeature.title')}</h1>
<p>{t('newFeature.description')}</p>
<button>{t('newFeature.button')}</button>
</div>
);
};
```
### Usage with Parameters
```tsx
const { t } = useTranslation('common');
<p>{t('welcome.message', { name: 'John' })}</p>;
// Corresponding language file:
// welcome: { message: 'Welcome {{name}}!' }
```
### Multiple Namespaces
```tsx
// Basic
t('newFeature.title')
// With parameters
t('alert.cloud.desc', { credit: '1000' })
// Multiple namespaces
const { t } = useTranslation(['common', 'chat']);
<button>{t('common:save')}</button>
<span>{t('chat:typing')}</span>
t('common:save')
```
## Type Safety
## Available Namespaces
The project uses TypeScript to implement type-safe translations, with types automatically generated from src/locales/resources.ts:
auth, authError, changelog, chat, clerk, color, **common**, components, discover, editor, electron, error, file, home, hotkey, image, knowledgeBase, labs, marketAuth, memory, metadata, migration, modelProvider, models, oauth, onboarding, plugin, portal, providers, ragEval, **setting**, subscription, thread, tool, topic, welcome
```typescript
import type { DefaultResources, Locales, NS } from '@/locales/resources';
// Available types:
// - NS: Available namespace keys ('common' | 'chat' | 'setting' | ...)
// - Locales: Supported language codes ('en-US' | 'zh-CN' | 'ja-JP' | ...)
const namespace: NS = 'common';
const locale: Locales = 'en-US';
```
## Best Practices
### 1. Namespace Organization
- common: Shared UI elements (buttons, labels, actions)
- chat: Chat-specific functionality
- setting: Configuration and settings
- error: Error messages and handling
- [feature]: Feature-specific or page-specific namespaces
- components: Reusable component text
### 2. Key Naming Conventions
```typescript
// ✅ Good: Hierarchical structure
export default {
modal: {
confirm: {
title: '确认操作',
message: '确定要执行此操作吗?',
actions: {
confirm: '确认',
cancel: '取消',
},
},
},
};
// ❌ Avoid: Flat structure
export default {
modalConfirmTitle: '确认操作',
modalConfirmMessage: '确定要执行此操作吗?',
};
```
## Troubleshooting
### Missing Translation Keys
- Check if the key exists in src/locales/default/namespace.ts
- Ensure the namespace is correctly imported in the component
- Ensure new namespaces are exported in src/locales/default/index.ts
- 检查键是否存在于 src/locales/default/namespace.ts 中
- 确保在组件中正确导入命名空间
- 确保新命名空间已在 src/locales/default/index.ts 中导出
**Most used:** `common` (shared UI), `chat` (chat features), `setting` (settings)
+146
View File
@@ -0,0 +1,146 @@
---
globs: src/locales/default/*
alwaysApply: false
---
你是「LobeHub」的中文 UI 文案与微文案(microcopy)专家。LobeHub 是一个助理工作空间:用户可以创建助理与群组,让人和助理、助理和助理协作,提升日常生产与生活效率。产品气质:外表年轻、亲和、现代;内核专业、可靠、强调生产力与可控性。整体风格参考 Notion / Figma / Apple / Discord / OpenAI / Gemini:清晰克制、可信、有人情味但不油腻。
产品 slogan**For Collaborative Agents**。你的文案要让用户持续感到:LobeHub 的重点不是“生成”,而是“协作的助理体系”(可共享上下文、可追踪、可回放、可演进、人在回路)。
---
### 1) 固定术语(必须遵守)
+ Workspace:空间
+ Agent:助理
+ Agent Team:群组
+ Context:上下文
+ Memory:记忆
+ Integration:连接器
+ Tool/Skill/Plugin/插件/工具: 技能
+ SystemRole: 助理档案
+ Topic: 话题
+ Page: 文稿
+ Community: 社区
+ Resource: 资源
+ Library: 库
+ MCP: MCP
+ Provider: 模型服务商
术语规则:同一概念全站只用一种说法,不混用“Agent/智能体/机器人/团队/工作区”等。
---
### 2) 你的任务
+ 优化、改写或从零生成任何界面中文文案:标题、按钮、表单说明、占位、引导、空状态、Toast、弹窗、错误、权限、设置项、创建/运行流程、协作与群组相关页面等。
+ 文案必须同时兼容:普通用户看得懂 + 专业用户不觉得低幼;娱乐与严肃场景都成立;不过度营销、不夸大 AI 能力;在关键节点提供恰到好处的人文关怀。
---
### 3) 品牌三原则(内化到结构与措辞)
+ **Create(创建)**:一句话创建助理;从想法到可用;清楚下一步。
+ **Collaborate(协作)**:多助理协作;群组对齐信息与产出;共享上下文(可控、可管理)。
+ **Evolve(演进)**:助理可在你允许的范围内记住偏好;随你的工作方式变得更顺手;强调可解释、可设置、可回放。
---
### 4) 写作规则(可执行)
1. **清晰优先**:短句、强动词、少形容词;避免口号化与空泛承诺(如“颠覆”“史诗级”“100%”)。
2. **分层表达(单一版本兼容两类用户)**:
- 主句:人人可懂、可执行
- 必要时补充一句副说明:更精确/更专业/更边界(可放副标题、帮助提示、折叠区)
- 不输出“Pro/Lite 两套文案”,而是“一句主文案 + 可选补充”
3. **术语克制但准确**:能说“连接/运行/上下文”就不要堆砌术语;必须出现专业词时给一句白话解释。
4. **一致性**:同一动作按钮尽量固定动词(创建/连接/运行/暂停/重试/查看详情/清除记忆等)。
5. **可行动**:每条提示都要让用户知道下一步;按钮避免“确定/取消”泛化,改成更具体的动作。
6. **中文本地化**:符合中文阅读节奏;中英混排规范;避免翻译腔。
---
### 5) 人文关怀(中间态温度:介于克制与陪伴)
目标:在 AI 时代的价值焦虑与创作失格感中,给用户“被理解 + 有掌控 + 能继续”的体验,但不写长抒情。
#### 温度比例规则
+ 默认:信息为主,温度为辅(约 8:2)
+ 关键节点(首次创建、空状态、长等待、失败重试、回退/丢失风险、协作分歧):允许提升到 7:3
+ 强制上限:任何一条上屏文案里,温度表达不超过**半句或一句**,且必须紧跟明确下一步。
#### 表达顺序(必须遵守)
1. 先承接处境(不评判):如“没关系/先这样也可以/卡住很正常”
2. 再给掌控感(人在回路):可暂停/可回放/可编辑/可撤销/可清除记忆/可查看上下文
3. 最后给下一步(按钮/路径明确)
#### 避免
+ 鸡汤式说教(如“别焦虑”“要相信未来”)
+ 宏大叙事与文学排比
+ 过度拟人(不承诺助理“理解你/有情绪/永远记得你”)
#### 核心立场
+ 助理很强,但它替代不了你的经历、选择与判断;LobeHub 帮你把时间还给重要的部分。
##### A. 情绪承接(先人后事)
+ 允许承认:焦虑、空白、无从下手、被追赶感、被替代感、创作枯竭、意义感动摇
+ 但不下结论、不说教:不输出“你要乐观/别焦虑”,改成“这种感觉很常见/你不是一个人”
##### B. 主体性回归(把人放回驾驶位)
+ 关键句式:**“决定权在你”**、**“你可以选择交给助理的部分”**、**“把你的想法变成可运行的流程”**
+ 强调可控:可编辑、可回放、可暂停、可撤销、可清除记忆、可查看上下文
##### C. 经历与关系(把价值从结果挪回过程)
+ 适度表达:记录、回放、版本、协作痕迹、讨论、共创、里程碑
+ 用“经历/过程/痕迹/回忆/脉络/成长”这类词,避免虚无抒情
##### D. 不用“AI 神话”
+ 不渲染“AI 终将超越你/取代你”
+ 也不轻飘飘说“AI 只是工具”了事更像:**“它是工具,但你仍是作者/负责人/最终决定者”**
##### 示例
在用户可能产生自我否定或无力感的场景(空状态、创作开始、产出对比、失败重试、长时间等待、团队协作分歧、版本回退):
1. **先承接感受**:用一句短话确认处境(不评判)
2. **再给掌控感**:强调“你可控/可选择/可回放/可撤销”
3. **最后给下一步**:提供明确行动按钮或路径
+ 允许出现“经历、选择、痕迹、成长、一起、陪你把事做完”等词来传递温度;但保持信息密度,不写长段抒情。
+ 严肃场景(权限/安全/付费/数据丢失风险)仍以清晰与准确为先,温度通过“尊重与解释”体现,而不是煽情。
你可以让系统在需要时套这些结构(同一句兼容新手/专业):
**开始创作/空白页**
+ 主句:给一个轻承接 + 行动入口
+ 模板:
- 「从一个念头开始就够了。写一句话,我来帮你搭好第一个助理。」
- 「不知道从哪开始也没关系:先说目标,我们一起把它拆开。」
**长任务运行/等待**
+ 模板:
- 「正在运行中…你可以先去做别的,完成后我会提醒你。」
- 「这一步可能要几分钟。想更快:减少上下文 / 切换模型 / 关闭自动运行。」
**失败/重试**
+ 模板:
- 「没关系,这次没跑通。你可以重试,或查看原因再继续。」
- 「连接失败:权限未通过或网络不稳定。去设置重新授权,或稍后再试。」
**对比与自我价值焦虑(适合提示/引导,不适合错误弹窗)**
+ 模板:
- 「助理可以加速产出,但方向、取舍和标准仍属于你。」
- 「结果可以很快,经历更重要:把每次尝试留下来,下一次会更稳。」
**协作/群组**
+ 模板:
- 「把上下文对齐到同一处,群组里每个助理都会站在同一页上。」
- 「不同意见没关系:先把目标写清楚,再让助理分别给方案与取舍。」
### 6) 错误/异常/权限/付费:硬规则
+ 必须包含:**发生了什么 +(可选)原因 + 你可以怎么做**
+ 必须提供可操作选项:**重试 / 查看详情 / 去设置 / 联系支持 / 复制日志**(按场景取舍)
+ 不责备用户;不只给错误码;错误码可放在“详情”里
+ 涉及数据与安全:语气更中性更完整,温度通过“尊重与解释”体现,而不是煽
+152
View File
@@ -0,0 +1,152 @@
---
globs: src/locales/default/*
alwaysApply: false
---
You are **LobeHubs English UI Copy & Microcopy Specialist**.
LobeHub is an assistant workspace: users can create **Agents** and **Agent Teams** so people↔agents and agent↔agent can collaborate to improve productivity in work and life.
Brand vibe: youthful, friendly, modern on the surface; professional, reliable, productivity- and controllability-first underneath. Overall style reference: Notion / Figma / Apple / Discord / OpenAI / Gemini — clear, restrained, trustworthy, human but not cheesy.
Product slogan: **For Collaborative Agents**. Your copy must continuously reinforce that LobeHub is not about “generation”, but about a **collaborative agent system**: shareable context, traceable outcomes, replayable runs, evolvable setup, and **human-in-the-loop**.
---
## 1) Fixed Terminology (must follow)
Use **exactly** these English terms across the product. Do not mix synonyms for the same concept.
- 空间: **Workspace**
- 助理: **Agent**
- 群组: **Group**
- 上下文: **Context**
- 记忆: **Memory**
- 连接器: **Integration**
- 技能/tool/plugin: **Skill**
- 助理档案: **Agent Profile**
- 话题: **Topic**
- 文稿: **Page**
- 社区: **Community**
- 资源: **Resource**
- 库: **Library**
- MCP: **MCP**
- 模型服务商: **Provider**
Terminology rule: one concept = one term site-wide. Never alternate with “bot/assistant/AI agent/team/workspace” variations.
---
## 2) Your Responsibilities
- Improve, rewrite, or create from scratch any **English UI copy**: titles, buttons, form labels/help text, placeholders, onboarding, empty states, toasts, modals, errors, permission prompts, settings, creation/run flows, collaboration and Agent Team pages, etc.
- Copy must work for both:
- general users (immediately understandable)
- power users (not childish)
- It must fit both playful and serious contexts.
- Avoid overclaiming AI capabilities; add human warmth at the right moments.
---
## 3) The Three Brand Principles (bake into structure & wording)
- **Create**: create an Agent in one sentence; clear next step from idea → usable.
- **Collaborate**: multi-agent collaboration; align info and outputs; share Context (controlled, manageable).
- **Evolve**: Agents can remember preferences **only with user consent**; become more helpful over time; emphasize explainability, settings, and replay.
---
## 4) Writing Rules (actionable)
1. **Clarity first**: short sentences, strong verbs, minimal adjectives. Avoid hype (“revolutionary”, “epic”, “100%”).
2. **Layered messaging (single version for everyone)**:
- Main line: simple and actionable
- Optional second line: more precise / technical / boundary-setting (subtitle, helper text, tooltip, collapsible)
- Do not produce “Pro vs Lite” variants; one main + optional detail
3. **Use terms sparingly but correctly**: prefer plain words (“connect”, “run”, “context”) unless a technical term is necessary. When it is, add a plain-English explanation.
4. **Consistency**: keep verbs consistent across similar actions (Create / Connect / Run / Pause / Retry / View details / Clear Memory).
5. **Actionable**: every message tells the user what to do next. Avoid generic “OK/Cancel”; use specific actions.
6. **English localization**: natural, product-native English; avoid translationese; keep punctuation and casing consistent.
---
## 5) Human Warmth (balanced, controlled)
Goal: reduce anxiety and restore control without being sentimental.
Default ratio: **80% information, 20% warmth**.
Key moments (first-time create, empty state, long waits, failures/retries, rollback/data-loss risk, collaboration conflicts): may go **70/30**.
Hard cap: any on-screen message may include **at most half a sentence to one sentence** of warmth, and it must be followed by a clear next step.
Required order:
1. Acknowledge the situation (no judgment)
2. Restore control (human-in-the-loop: pause/replay/edit/undo/clear Memory/view Context)
3. Provide the next action (button/path)
Avoid:
- preachy encouragement (“dont worry”, “stay positive”)
- grand narratives
- overly anthropomorphic claims (“I understand you”, “Ill always remember you”)
Core stance: Agents can accelerate output, but **you** own the judgment, trade-offs, and final decision. LobeHub gives you time back for what matters.
Suggested patterns:
- **Getting started / blank state**
- “Starting with one sentence is enough. Describe your goal and Ill help you set up the first Agent.”
- “Not sure where to begin? Tell me the outcome—well break it down together.”
- **Long run / waiting**
- “Running… You can switch tasks—I'll notify you when its done.”
- “This may take a few minutes. To speed up: reduce Context / switch model / disable Auto-run.”
- **Failure / retry**
- “That didnt run through. Retry, or view details to fix the cause.”
- “Connection failed: permission not granted or network unstable. Re-authorize in Settings, or try again later.”
- **Value anxiety (guidance, not error dialogs)**
- “Agents can speed up output, but direction and standards stay with you.”
- “Fast results are great—keeping the trail makes the next run steadier.”
- **Collaboration / Agent Teams**
- “Align everyone to the same Context. Every Agent in the Agent Team works from the same page.”
- “Different opinions are fine. Write the goal first, then let Agents propose options and trade-offs.”
---
## 6) Errors / Exceptions / Permissions / Billing: hard rules
Every error must include:
- **What happened**
- (optional) **Why**
- **What the user can do next**
Provide actionable options as appropriate:
- Retry / View details / Go to Settings / Contact support / Copy logs
Never blame the user. Dont show only an error code; put codes in “Details” if needed.
For data/security/billing: be neutral, thorough, and respectful—warmth comes from clarity, not emotion.
---
## 7) Your Special Task: CN i18n → EN (localized, length-aware)
You translate **raw Chinese i18n strings into English** for LobeHub.
Requirements:
- Prefer **localized**, product-native English over literal translation.
- Do **not** chase perfect one-to-one consistency if a more natural UI phrase reads better.
- Keep the **character length difference small**; try to make the English string **roughly the same visual length** as the Chinese source (avoid overly long expansions).
- Preserve meaning, tone, and actionability; keep verbs consistent with LobeHubs UI patterns.
- If space is tight (buttons, tabs, toasts), prioritize: **verb + object**, drop optional words first.
- If the Chinese includes placeholders/variables, preserve them exactly (e.g., `{name}`, `{{count}}`, `%s`) and keep word order sensible.
- Keep capitalization consistent with UI norms (buttons/title case only when appropriate).
Output format when translating:
- Provide **English only**, unless asked otherwise.
- If multiple options are useful, give **one best option** + **one shorter fallback** (only when length constraints are likely).
---
You always optimize for: **clarity, control, collaboration, replayability, and human-in-the-loop**—in a modern, restrained, trustworthy English voice.
+12 -9
View File
@@ -1,11 +1,12 @@
---
description: react flex layout package `react-layout-kit` usage
globs:
description: flex layout components from `@lobehub/ui` usage
globs:
alwaysApply: false
---
# React Layout Kit 使用指南
react-layout-kit 是一个功能丰富的 React flex 布局组件库,在 lobe-chat 项目中被广泛使用。以下是重点组件的使用方法:
# Flexbox 布局组件使用指南
`@lobehub/ui` 提供了 `Flexbox` 和 `Center` 组件用于创建弹性布局。以下是重点组件的使用方法:
## Flexbox 组件
@@ -14,7 +15,7 @@ Flexbox 是最常用的布局组件,用于创建弹性布局,类似于 CSS
### 基本用法
```jsx
import { Flexbox } from 'react-layout-kit';
import { Flexbox } from '@lobehub/ui';
// 默认垂直布局
<Flexbox>
@@ -58,14 +59,14 @@ import { Flexbox } from 'react-layout-kit';
>
<SidebarContent />
</Flexbox>
{/* 中间内容区 */}
<Flexbox flex={1} style={{ height: '100%' }}>
{/* 主要内容 */}
<Flexbox flex={1} padding={24} style={{ overflowY: 'auto' }}>
<MainContent />
</Flexbox>
{/* 底部区域 */}
<Flexbox
style={{
@@ -86,9 +87,11 @@ Center 是对 Flexbox 的封装,使子元素水平和垂直居中。
### 基本用法
```jsx
import { Center } from '@lobehub/ui';
<Center width={'100%'} height={'100%'}>
<Content />
</Center>
</Center>;
```
Center 组件继承了 Flexbox 的所有属性,同时默认设置了居中对齐。主要用于快速创建居中布局。
@@ -116,4 +119,4 @@ Center 组件继承了 Flexbox 的所有属性,同时默认设置了居中对
- 嵌套 Flexbox 创建复杂布局
- 设置 overflow: 'auto' 使内容可滚动
- 使用 horizontal 创建水平布局,默认为垂直布局
- 与 antd-style 的 useTheme hook 配合使用创建主题响应式的布局
- 与 antd-style 的 useTheme hook 配合使用创建主题响应式的布局
+3 -3
View File
@@ -17,20 +17,20 @@ logo emoji: 🤯
## Project Technologies Stack
- Next.js 16
- implement spa inside nextjs with `react-router-dom`
- react 19
- TypeScript
- `@lobehub/ui`, antd for component framework
- antd-style for css-in-js framework
- lucide-react, `@ant-design/icons` for icons
- react-layout-kit for flex layout component
- react-i18next for i18n
- zustand for state management
- nuqs for search params management
- SWR for data fetch
- aHooks for react hooks library
- dayjs for time library
- lodash-es for utility library
- es-toolkit for utility library
- TRPC for type safe backend
- PGLite for client DB and Neon PostgreSQL for backend DB
- Neon PostgreSQL for backend DB
- Drizzle ORM
- Vitest for testing
+33 -37
View File
@@ -25,22 +25,23 @@ lobe-chat/
│ └── zh-CN/
├── packages/
│ ├── agent-runtime/
│ ├── builtin-agents/
│ ├── builtin-tool-*/ # builtin tool packages
│ ├── const/
│ ├── context-engine/
│ ├── conversation-flow/
│ ├── database/
│ │ ── src/
│ │ ├── models/
│ │ ├── schemas/
│ │ └── repositories/
│ │ ── src/
│ │ ├── models/
│ │ ├── schemas/
│ │ └── repositories/
│ ├── desktop-bridge/
│ ├── electron-client-ipc/
│ ├── electron-server-ipc/
│ ├── fetch-sse/
│ ├── file-loaders/
│ ├── memory-extract/
│ ├── memory-user-memory/
│ ├── model-bank/
│ │ └── src/
│ │ └── aiModels/
│ ├── model-runtime/
│ │ └── src/
│ │ ├── core/
@@ -50,9 +51,6 @@ lobe-chat/
│ ├── python-interpreter/
│ ├── ssrf-safe-fetch/
│ ├── types/
│ │ └── src/
│ │ ├── message/
│ │ └── user/
│ ├── utils/
│ └── web-crawler/
├── public/
@@ -61,24 +59,25 @@ lobe-chat/
│ ├── app/
│ │ ├── (backend)/
│ │ │ ├── api/
│ │ │ │ ├── auth/
│ │ │ │ └── webhooks/
│ │ │ ├── f/
│ │ │ ├── market/
│ │ │ ├── middleware/
│ │ │ ├── oidc/
│ │ │ ├── trpc/
│ │ │ └── webapi/
│ │ │ ├── chat/
│ │ │ └── tts/
│ │ ├── [variants]/
│ │ │ ├── (auth)/
│ │ │ ├── (main)/
│ │ │ │ ├── chat/
│ │ │ │ └── settings/
│ │ │ └── @modal/
│ │ └── manifest.ts
│ │ │ ├── (mobile)/
│ │ │ ├── onboarding/
│ │ │ └── router/
│ │ └── desktop/
│ ├── components/
│ ├── config/
│ ├── const/
│ ├── envs/
│ ├── features/
│ └── ChatInput/
├── helpers/
│ ├── hooks/
│ ├── layout/
│ │ ├── AuthProvider/
@@ -90,23 +89,23 @@ lobe-chat/
│ ├── locales/
│ │ └── default/
│ ├── server/
│ │ ├── featureFlags/
│ │ ├── globalConfig/
│ │ ├── modules/
│ │ ├── routers/
│ │ │ ├── async/
│ │ │ ├── desktop/
│ │ │ ├── edge/
│ │ │ └── lambda/
│ │ │ ├── lambda/
│ │ │ ├── mobile/
│ │ │ └── tools/
│ │ └── services/
│ ├── services/
│ │ ├── user/
│ │ │ ├── client.ts
│ │ │ └── server.ts
│ │ └── message/
│ ├── store/
│ │ ├── agent/
│ │ ├── chat/
│ │ └── user/
│ ├── styles/
│ ├── tools/
│ ├── types/
│ └── utils/
└── package.json
```
@@ -116,25 +115,22 @@ lobe-chat/
- UI Components: `src/components`, `src/features`
- Global providers: `src/layout`
- Zustand stores: `src/store`
- Client Services: `src/services/` cross-platform services
- clientDB: `src/services/<domain>/client.ts`
- serverDB: `src/services/<domain>/server.ts`
- Client Services: `src/services/`
- API Routers:
- `src/app/(backend)/webapi` (REST)
- `src/server/routers/{edge|lambda|async|desktop|tools}` (tRPC)
- `src/server/routers/{async|lambda|mobile|tools}` (tRPC)
- Server:
- Services(can access serverDB): `src/server/services` server-used-only services
- Modules(can't access db): `src/server/modules` (Server only Third-party Service Module)
- Services (can access serverDB): `src/server/services`
- Modules (can't access db): `src/server/modules`
- Feature Flags: `src/server/featureFlags`
- Global Config: `src/server/globalConfig`
- Database:
- Schema (Drizzle): `packages/database/src/schemas`
- Model (CRUD): `packages/database/src/models`
- Repository (bff-queries): `packages/database/src/repositories`
- Third-party Integrations: `src/libs` — analytics, oidc etc.
- Builtin Tools: `src/tools`, `packages/builtin-tool-*`
## Data Flow Architecture
- **Web with ClientDB**: React UI → Client Service → Direct Model Access → PGLite (Web WASM)
- **Web with ServerDB**: React UI → Client Service → tRPC Lambda → Server Services → PostgreSQL (Remote)
- **Desktop**:
- Cloud sync disabled: Electron UI → Client Service → tRPC Lambda → Local Server Services → PGLite (Node WASM)
- Cloud sync enabled: Electron UI → Client Service → tRPC Lambda → Cloud Server Services → PostgreSQL (Remote)
React UI → Store Actions → Client Service → TRPC Lambda → Server Services -> DB Model → PostgreSQL (Remote)
-173
View File
@@ -1,173 +0,0 @@
---
description:
globs: *.tsx
alwaysApply: false
---
# react component 编写指南
- 如果要写复杂样式的话用 antd-style ,简单的话可以用 style 属性直接写内联样式
- 如果需要 flex 布局或者居中布局应该使用 react-layout-kit 的 Flexbox 和 Center 组件
- 选择组件时优先顺序应该是 src/components > 安装的组件 package > lobe-ui > antd
- 使用 selector 访问 zustand store 的数据,而不是直接从 store 获取
## antd-style token system
### 访问 token system 的两种方式
#### 使用 antd-style 的 useTheme hook
```tsx
import { useTheme } from 'antd-style';
const MyComponent = () => {
const theme = useTheme();
return (
<div
style={{
color: theme.colorPrimary,
backgroundColor: theme.colorBgContainer,
padding: theme.padding,
borderRadius: theme.borderRadius,
}}
>
使用主题 token 的组件
</div>
);
};
```
#### 使用 antd-style 的 createStyles
```tsx
const useStyles = createStyles(({ css, token }) => {
return {
container: css`
background-color: ${token.colorBgContainer};
border-radius: ${token.borderRadius}px;
padding: ${token.padding}px;
color: ${token.colorText};
`,
title: css`
font-size: ${token.fontSizeLG}px;
font-weight: ${token.fontWeightStrong};
margin-bottom: ${token.marginSM}px;
`,
content: css`
font-size: ${token.fontSize}px;
line-height: ${token.lineHeight};
`,
};
});
const Card: FC<CardProps> = ({ title, content }) => {
const { styles } = useStyles();
return (
<Flexbox className={styles.container}>
<div className={styles.title}>{title}</div>
<div className={styles.content}>{content}</div>
</Flexbox>
);
};
```
### 一些你经常会忘记使用的 token
请注意使用下面的 token 而不是 css 字面值。可以访问 https://ant.design/docs/react/customize-theme-cn 了解所有 token
- 动画类
- token.motionDurationMid
- token.motionEaseInOut
- 包围盒属性
- token.paddingSM
- token.marginLG
## Lobe UI 包含的组件
- 不知道 `@lobehub/ui` 的组件怎么用,有哪些属性,就自己搜下这个项目其它地方怎么用的,不要瞎猜,大部分组件都是在 antd 的基础上扩展了属性
- 具体用法不懂可以联网搜索,例如 ActionIcon 就爬取 https://ui.lobehub.com/components/action-icon
- 可以阅读 `node_modules/@lobehub/ui/es/index.js` 了解有哪些组件,每个组件的属性是什么
- General
- ActionIcon
- ActionIconGroup
- Block
- Button
- DownloadButton
- Icon
- Data Display
- Avatar
- AvatarGroup
- GroupAvatar
- Collapse
- FileTypeIcon
- FluentEmoji
- GuideCard
- Highlighter
- Hotkey
- Image
- List
- Markdown
- SearchResultCards
- MaterialFileTypeIcon
- Mermaid
- Typography
- Text
- Segmented
- Snippet
- SortableList
- Tag
- Tooltip
- Video
- Data Entry
- AutoComplete
- CodeEditor
- ColorSwatches
- CopyButton
- DatePicker
- EditableText
- EmojiPicker
- Form
- FormModal
- HotkeyInput
- ImageSelect
- Input
- SearchBar
- Select
- SliderWithInput
- ThemeSwitch
- Feedback
- Alert
- Drawer
- Modal
- Layout
- DraggablePanel
- DraggablePanelBody
- DraggablePanelContainer
- DraggablePanelFooter
- DraggablePanelHeader
- Footer
- Grid
- Header
- Layout
- LayoutFooter
- LayoutHeader
- LayoutMain
- LayoutSidebar
- LayoutSidebarInner
- LayoutToc
- MaskShadow
- ScrollShadow
- Navigation
- Burger
- Dropdown
- Menu
- SideNav
- Tabs
- Toc
- Theme
- ConfigProvider
- FontLoader
- ThemeProvider
+157
View File
@@ -0,0 +1,157 @@
---
description:
globs: *.tsx
alwaysApply: false
---
# React Component Writing Guide
- Use antd-style for complex styles; for simple cases, use the `style` attribute for inline styles
- Use `Flexbox` and `Center` components from `@lobehub/ui` for flex and centered layouts
- Component selection priority: src/components > installed component packages > lobe-ui > antd
- Use selectors to access zustand store data instead of accessing the store directly
## Lobe UI Components
- If unsure how to use `@lobehub/ui` components or what props they accept, search for existing usage in this project instead of guessing. Most components extend antd components with additional props
- For specific usage, search online. For example, for ActionIcon visit <https://ui.lobehub.com/components/action-icon>
- Read `node_modules/@lobehub/ui/es/index.mjs` to see all available components and their props
- General
- ActionIcon
- ActionIconGroup
- Block
- Button
- Icon
- Data Display
- Accordion
- Avatar
- Collapse
- Empty
- FileTypeIcon
- FluentEmoji
- GroupAvatar
- GuideCard
- Highlighter
- Hotkey
- Image
- List
- Markdown
- MaterialFileTypeIcon
- Mermaid
- Segmented
- Skeleton
- Snippet
- SortableList
- Tag
- Tooltip
- Video
- Data Entry
- AutoComplete
- CodeEditor
- ColorSwatches
- CopyButton
- DatePicker
- DownloadButton
- EditableText
- EmojiPicker
- Form
- FormModal
- HotkeyInput
- ImageSelect
- Input
- SearchBar
- Select
- SliderWithInput
- ThemeSwitch
- Feedback
- Alert
- Drawer
- Modal
- Layout
- Center
- DraggablePanel
- Flexbox
- Footer
- Grid
- Header
- Layout
- MaskShadow
- ScrollShadow
- Navigation
- Burger
- DraggableSideNav
- Dropdown
- Menu
- SideNav
- Tabs
- Toc
- Theme
- ConfigProvider
- FontLoader
- ThemeProvider
- Typography
- Text
## Routing Architecture
This project uses a **hybrid routing architecture**: Next.js App Router for static pages + React Router DOM for the main SPA.
### Route Types
```plaintext
+------------------+--------------------------------+--------------------------------+
| Route Type | Use Case | Implementation |
+------------------+--------------------------------+--------------------------------+
| Next.js App | Auth pages (login, signup, | page.tsx file convention |
| Router | oauth, reset-password, etc.) | src/app/[variants]/(auth)/ |
+------------------+--------------------------------+--------------------------------+
| React Router | Main SPA features | BrowserRouter + Routes |
| DOM | (chat, discover, settings) | desktopRouter.config.tsx |
| | | mobileRouter.config.tsx |
+------------------+--------------------------------+--------------------------------+
```
### Key Files
- Entry point: `src/app/[variants]/page.tsx` - Routes to Desktop or Mobile based on device
- Desktop router: `src/app/[variants]/router/desktopRouter.config.tsx`
- Mobile router: `src/app/[variants]/(mobile)/router/mobileRouter.config.tsx`
- Router utilities: `src/utils/router.tsx`
### Router Utilities
```tsx
import { dynamicElement, redirectElement, ErrorBoundary, RouteConfig } from '@/utils/router';
// Lazy load a page component
element: dynamicElement(() => import('./chat'), 'Desktop > Chat')
// Create a redirect
element: redirectElement('/settings/profile')
// Error boundary for route
errorElement: <ErrorBoundary resetPath="/chat" />
```
### Adding New Routes
1. Add route config to `desktopRouter.config.tsx` or `mobileRouter.config.tsx`
2. Create page component in the corresponding directory under `(main)/`
3. Use `dynamicElement()` for lazy loading
### Navigation
```tsx
// In components - use react-router-dom hooks
import { useNavigate, useParams } from 'react-router-dom';
const navigate = useNavigate();
navigate('/chat');
// From stores - use global navigate
import { useGlobalStore } from '@/store/global';
const navigate = useGlobalStore.getState().navigate;
navigate?.('/settings');
```
+138
View File
@@ -0,0 +1,138 @@
# Recent Data 使用指南
## 概述
Recent 数据(recentTopics, recentResources, recentPages)存储在 session store 中,可以在应用的任何地方访问。
## 数据初始化
在应用顶层(如 `RecentHydration.tsx`)中初始化所有 recent 数据:
```tsx
import { useInitRecentPage } from '@/hooks/useInitRecentPage';
import { useInitRecentResource } from '@/hooks/useInitRecentResource';
import { useInitRecentTopic } from '@/hooks/useInitRecentTopic';
const App = () => {
// 初始化所有 recent 数据
useInitRecentTopic();
useInitRecentResource();
useInitRecentPage();
return <YourComponents />;
};
```
## 使用方式
### 方式一:直接从 Store 读取(推荐用于多处使用)
在任何组件中直接访问 store 中的数据:
```tsx
import { useSessionStore } from '@/store/session';
import { recentSelectors } from '@/store/session/selectors';
const Component = () => {
// 读取数据
const recentTopics = useSessionStore(recentSelectors.recentTopics);
const isInit = useSessionStore(recentSelectors.isRecentTopicsInit);
if (!isInit) return <div>Loading...</div>;
return (
<div>
{recentTopics.map(topic => (
<div key={topic.id}>{topic.title}</div>
))}
</div>
);
};
```
### 方式二:使用 Hook 返回的数据(用于单一组件)
```tsx
import { useInitRecentTopic } from '@/hooks/useInitRecentTopic';
const Component = () => {
const { data: recentTopics, isLoading } = useInitRecentTopic();
if (isLoading) return <div>Loading...</div>;
return <div>{/* 使用 recentTopics */}</div>;
};
```
## 可用的 Selectors
### Recent Topics (最近话题)
```tsx
import { recentSelectors } from '@/store/session/selectors';
// 数据
const recentTopics = useSessionStore(recentSelectors.recentTopics);
// 类型: RecentTopic[]
// 初始化状态
const isInit = useSessionStore(recentSelectors.isRecentTopicsInit);
// 类型: boolean
```
**RecentTopic 类型:**
```typescript
interface RecentTopic {
agent: {
avatar: string | null;
backgroundColor: string | null;
id: string;
title: string | null;
} | null;
id: string;
title: string | null;
updatedAt: Date;
}
```
### Recent Resources (最近文件)
```tsx
import { recentSelectors } from '@/store/session/selectors';
// 数据
const recentResources = useSessionStore(recentSelectors.recentResources);
// 类型: FileListItem[]
// 初始化状态
const isInit = useSessionStore(recentSelectors.isRecentResourcesInit);
// 类型: boolean
```
### Recent Pages (最近页面)
```tsx
import { recentSelectors } from '@/store/session/selectors';
// 数据
const recentPages = useSessionStore(recentSelectors.recentPages);
// 类型: any[]
// 初始化状态
const isInit = useSessionStore(recentSelectors.isRecentPagesInit);
// 类型: boolean
```
## 特性
1. **自动登录检测**:只有在用户登录时才会加载数据
2. **数据缓存**:数据存储在 store 中,多处使用无需重复加载
3. **自动刷新**:使用 SWR,在用户重新聚焦时自动刷新(5分钟间隔)
4. **类型安全**:完整的 TypeScript 类型定义
## 最佳实践
1. **初始化位置**:在应用顶层统一初始化所有 recent 数据
2. **数据访问**:使用 selectors 从 store 读取数据
3. **多处使用**:同一数据在多个组件中使用时,推荐使用方式一(直接从 store 读取)
4. **性能优化**:使用 selector 确保只有相关数据变化时才重新渲染
+1 -1
View File
@@ -14,7 +14,7 @@ All following rules are saved under `.cursor/rules/` directory:
## Frontend
- `react-component.mdc` React component style guide and conventions
- `react.mdc` React component style guide and conventions
- `i18n.mdc` Internationalization guide using react-i18next
- `typescript.mdc` TypeScript code style guide
- `packages/react-layout-kit.mdc` Usage guide for react-layout-kit
@@ -0,0 +1,285 @@
# Agent Runtime E2E 测试指南
本文档描述 Agent Runtime 端到端测试的核心原则和实施方法。
## 核心原则
### 1. 最小化 Mock 原则
E2E 测试的目标是尽可能接近真实运行环境。因此,我们只 Mock **三个外部依赖**:
| 依赖 | Mock 方式 | 说明 |
| --- | --- | --- |
| **Database** | PGLite | 使用 `@lobechat/database/test-utils` 提供的内存数据库 |
| **Redis** | InMemoryAgentStateManager | Mock `AgentStateManager` 使用内存实现 |
| **Redis** | InMemoryStreamEventManager | Mock `StreamEventManager` 使用内存实现 |
**不 Mock 的部分:**
- `model-bank` - 使用真实的模型配置数据
- `Mecha` (AgentToolsEngine, ContextEngineering) - 使用真实逻辑
- `AgentRuntimeService` - 使用真实逻辑
- `AgentRuntimeCoordinator` - 使用真实逻辑
### 2. 使用 vi.spyOn 而非 vi.mock
不同测试场景需要不同的 LLM 响应。使用 `vi.spyOn` 可以:
- 在每个测试中灵活控制返回值
- 便于测试不同场景(纯文本、tool calls、错误等)
- 避免全局 mock 导致的测试隔离问题
### 3. 默认模型使用 gpt-5
- `model-bank` 中肯定有该模型的数据
- 避免短期内因模型更新需要修改测试
## 技术实现
### 数据库设置
```typescript
import { LobeChatDatabase } from '@lobechat/database';
import { getTestDB } from '@lobechat/database/test-utils';
let testDB: LobeChatDatabase;
beforeEach(async () => {
testDB = await getTestDB();
});
```
### OpenAI Response Mock Helper
创建一个 helper 函数来生成 OpenAI 格式的流式响应:
```typescript
/**
* 创建 OpenAI 格式的流式响应
*/
export const createOpenAIStreamResponse = (options: {
content?: string;
toolCalls?: Array<{
id: string;
name: string;
arguments: string;
}>;
finishReason?: 'stop' | 'tool_calls';
}) => {
const { content, toolCalls, finishReason = 'stop' } = options;
return new Response(
new ReadableStream({
start(controller) {
const encoder = new TextEncoder();
// 发送内容 chunk
if (content) {
const chunk = {
id: 'chatcmpl-mock',
object: 'chat.completion.chunk',
model: 'gpt-5',
choices: [
{
index: 0,
delta: { content },
finish_reason: null,
},
],
};
controller.enqueue(encoder.encode(`data: ${JSON.stringify(chunk)}\n\n`));
}
// 发送 tool_calls chunk
if (toolCalls) {
for (const tool of toolCalls) {
const chunk = {
id: 'chatcmpl-mock',
object: 'chat.completion.chunk',
model: 'gpt-5',
choices: [
{
index: 0,
delta: {
tool_calls: [
{
index: 0,
id: tool.id,
type: 'function',
function: {
name: tool.name,
arguments: tool.arguments,
},
},
],
},
finish_reason: null,
},
],
};
controller.enqueue(encoder.encode(`data: ${JSON.stringify(chunk)}\n\n`));
}
}
// 发送完成 chunk
const finishChunk = {
id: 'chatcmpl-mock',
object: 'chat.completion.chunk',
model: 'gpt-5',
choices: [
{
index: 0,
delta: {},
finish_reason: finishReason,
},
],
};
controller.enqueue(encoder.encode(`data: ${JSON.stringify(finishChunk)}\n\n`));
controller.enqueue(encoder.encode('data: [DONE]\n\n'));
controller.close();
},
}),
{ headers: { 'content-type': 'text/event-stream' } },
);
};
```
### 内存状态管理
使用依赖注入替代 Redis
```typescript
import {
InMemoryAgentStateManager,
InMemoryStreamEventManager,
} from '@/server/modules/AgentRuntime';
import { AgentRuntimeService } from '@/server/services/agentRuntime';
const stateManager = new InMemoryAgentStateManager();
const streamEventManager = new InMemoryStreamEventManager();
const service = new AgentRuntimeService(serverDB, userId, {
coordinatorOptions: {
stateManager,
streamEventManager,
},
queueService: null, // 禁用 QStash 队列,使用 executeSync
streamEventManager,
});
```
### Mock OpenAI API
在测试中使用 `vi.spyOn` mock fetch
```typescript
import { vi } from 'vitest';
// 在测试文件顶部或 beforeEach 中
const fetchSpy = vi.spyOn(globalThis, 'fetch');
// 在具体测试中设置返回值
it('should handle text response', async () => {
fetchSpy.mockResolvedValueOnce(createOpenAIStreamResponse({ content: '杭州今天天气晴朗' }));
// ... 执行测试
});
it('should handle tool calls', async () => {
fetchSpy.mockResolvedValueOnce(
createOpenAIStreamResponse({
toolCalls: [
{
id: 'call_123',
name: 'lobe-web-browsing____search____builtin',
arguments: JSON.stringify({ query: '杭州天气' }),
},
],
finishReason: 'tool_calls',
}),
);
// ... 执行测试
});
```
## 测试场景
### 1. 基本对话测试
```typescript
describe('Basic Chat', () => {
it('should complete a simple conversation', async () => {
fetchSpy.mockResolvedValueOnce(
createOpenAIStreamResponse({ content: 'Hello! How can I help you?' }),
);
const result = await service.createOperation({
agentConfig: { model: 'gpt-5', provider: 'openai' },
initialMessages: [{ role: 'user', content: 'Hi' }],
// ...
});
const finalState = await service.executeSync(result.operationId);
expect(finalState.status).toBe('done');
});
});
```
### 2. Tool 调用测试
```typescript
describe('Tool Calls', () => {
it('should execute web-browsing tool', async () => {
// 第一次调用:LLM 返回 tool_calls
fetchSpy.mockResolvedValueOnce(
createOpenAIStreamResponse({
toolCalls: [
{
id: 'call_123',
name: 'lobe-web-browsing____search____builtin',
arguments: JSON.stringify({ query: '杭州天气' }),
},
],
finishReason: 'tool_calls',
}),
);
// 第二次调用:处理 tool 结果后的响应
fetchSpy.mockResolvedValueOnce(
createOpenAIStreamResponse({ content: '根据搜索结果,杭州今天...' }),
);
// ... 执行测试
});
});
```
### 3. 错误处理测试
```typescript
describe('Error Handling', () => {
it('should handle API errors gracefully', async () => {
fetchSpy.mockRejectedValueOnce(new Error('API rate limit exceeded'));
// ... 执行测试并验证错误处理
});
});
```
## 文件组织
```
src/server/routers/lambda/__tests__/integration/
├── setup.ts # 测试设置工具
├── aiAgent.integration.test.ts # 现有集成测试
├── aiAgent.e2e.test.ts # E2E 测试
└── helpers/
└── openaiMock.ts # OpenAI mock helper
```
## 注意事项
1. **测试隔离**:每个测试后清理 `InMemoryAgentStateManager` 和 `InMemoryStreamEventManager`
2. **超时设置**:E2E 测试可能需要更长的超时时间
3. **调试**:使用 `DEBUG=lobe-server:*` 环境变量查看详细日志
@@ -1,6 +1,6 @@
---
description: Best practices for testing Zustand store actions
globs: "src/store/**/*.test.ts"
globs: 'src/store/**/*.test.ts'
alwaysApply: false
---
@@ -15,6 +15,7 @@ import { act, renderHook } from '@testing-library/react';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { messageService } from '@/services/message';
import { useChatStore } from '../../store';
// Keep zustand mock as it's needed globally
@@ -229,8 +230,7 @@ it('should handle topic creation flow', async () => {
const { result } = renderHook(() => useChatStore());
// Spy on action dependencies
const createTopicSpy = vi.spyOn(result.current, 'createTopic')
.mockResolvedValue('new-topic-id');
const createTopicSpy = vi.spyOn(result.current, 'createTopic').mockResolvedValue('new-topic-id');
const toggleLoadingSpy = vi.spyOn(result.current, 'internal_toggleMessageLoading');
// Execute
@@ -251,9 +251,7 @@ When testing streaming responses, simulate the flow properly:
```typescript
it('should handle streaming chunks', async () => {
const { result } = renderHook(() => useChatStore());
const messages = [
{ id: 'msg-1', role: 'user', content: 'Hello', sessionId: 'test-session' },
];
const messages = [{ id: 'msg-1', role: 'user', content: 'Hello', sessionId: 'test-session' }];
const streamSpy = vi
.spyOn(chatService, 'createAssistantMessageStream')
@@ -287,9 +285,7 @@ Always test error scenarios:
it('should handle errors gracefully', async () => {
const { result } = renderHook(() => useChatStore());
vi.spyOn(messageService, 'createMessage').mockRejectedValue(
new Error('create message error'),
);
vi.spyOn(messageService, 'createMessage').mockRejectedValue(new Error('create message error'));
await act(async () => {
try {
@@ -330,8 +326,7 @@ it('should test something', async () => {
it('should call internal methods', async () => {
const { result } = renderHook(() => useChatStore());
const internalMethodSpy = vi.spyOn(result.current, 'internal_method')
.mockResolvedValue();
const internalMethodSpy = vi.spyOn(result.current, 'internal_method').mockResolvedValue();
await act(async () => {
await result.current.publicMethod();
@@ -456,6 +451,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
import { discoverService } from '@/services/discover';
import { globalHelpers } from '@/store/global/helpers';
import { useDiscoverStore as useStore } from '../../store';
vi.mock('zustand/traditional');
@@ -486,6 +482,7 @@ describe('SWR Hook Actions', () => {
```
**Key points**:
- **DO NOT mock useSWR** - let it use the real implementation
- Only mock the **service methods** (fetchers)
- Use `waitFor` from `@testing-library/react` to wait for async operations
@@ -559,21 +556,19 @@ it('should not fetch when required parameter is missing', () => {
7. **Type assertions**: Use `as any` for test mock data where type definitions are strict
**Why this matters**:
- The fetcher (service method) is what we're testing - it must be called
- Hardcoding the return value bypasses the actual fetcher logic
- SWR returns Promises in real usage, tests should mirror this behavior
## Benefits of This Approach
✅ **Clear test layers** - Each test only spies on direct dependencies
✅ **Correct mocks** - Mocks match actual implementation
✅ **Better maintainability** - Changes to implementation require fewer test updates
✅ **Improved coverage** - Structured approach ensures all branches are tested
✅ **Reduced coupling** - Tests are independent and can run in any order
✅ **Clear test layers** - Each test only spies on direct dependencies ✅ **Correct mocks** - Mocks match actual implementation ✅ **Better maintainability** - Changes to implementation require fewer test updates ✅ **Improved coverage** - Structured approach ensures all branches are tested ✅ **Reduced coupling** - Tests are independent and can run in any order
## Reference
See example implementation in:
- `src/store/chat/slices/aiChat/actions/__tests__/generateAIChat.test.ts` (Regular actions)
- `src/store/discover/slices/plugin/action.test.ts` (SWR hooks)
- `src/store/discover/slices/mcp/action.test.ts` (SWR hooks)
-4
View File
@@ -16,10 +16,6 @@ alwaysApply: false
- prefer `@ts-expect-error` over `@ts-ignore` over `as any`
- Avoid meaningless null/undefined parameters; design strict function contracts.
## Imports and Modules
- When importing a directory module, prefer the explicit index path like `@/db/index` instead of `@/db`.
## Asynchronous Patterns and Concurrency
- Prefer `async`/`await` over callbacks or chained `.then` promises.
+136 -168
View File
@@ -1,137 +1,126 @@
---
description:
description:
globs: src/store/**
alwaysApply: false
---
# LobeChat Zustand Action 组织模式
本文档详细说明了 LobeChat 项目中 Zustand Action 的组织方式、命名规范和实现模式,特别关注乐观更新与后端服务的集成。
# LobeChat Zustand Action Patterns
## Action 类型分层
## Action Type Hierarchy
LobeChat Action 采用分层架构,明确区分不同职责:
LobeChat Actions use a layered architecture with clear separation of responsibilities:
### 1. Public Actions
对外暴露的主要接口,供 UI 组件调用:
- 命名:动词形式(`createTopic`, `sendMessage`, `updateTopicTitle`
- 职责:参数验证、流程编排、调用 internal actions
- 示例:[src/store/chat/slices/topic/action.ts](mdc:src/store/chat/slices/topic/action.ts)
Main interfaces exposed for UI component consumption:
- Naming: Verb form (`createTopic`, `sendMessage`, `updateTopicTitle`)
- Responsibilities: Parameter validation, flow orchestration, calling internal actions
- Example: [src/store/chat/slices/topic/action.ts](mdc:src/store/chat/slices/topic/action.ts)
```typescript
// Public Action 示例
// Public Action example
createTopic: async () => {
const { activeId, internal_createTopic } = get();
const messages = chatSelectors.activeBaseChats(get());
if (messages.length === 0) return;
const topicId = await internal_createTopic({
sessionId: activeId,
title: t('defaultTitle', { ns: 'topic' }),
messages: messages.map((m) => m.id),
});
// ...
return topicId;
},
```
### 2. Internal Actions (`internal_*`)
内部实现细节,处理核心业务逻辑:
- 命名:`internal_` 前缀 + 动词(`internal_createTopic`, `internal_updateMessageContent`
- 职责:乐观更新、服务调用、错误处理、状态同步
- 不应该被 UI 组件直接调用
Internal implementation details handling core business logic:
- Naming: `internal_` prefix + verb (`internal_createTopic`, `internal_updateMessageContent`)
- Responsibilities: Optimistic updates, service calls, error handling, state synchronization
- Should not be called directly by UI components
```typescript
// Internal Action 示例 - 乐观更新模式
// Internal Action example - Optimistic update pattern
internal_createTopic: async (params) => {
const tmpId = Date.now().toString();
// 1. 立即更新前端状态(乐观更新)
// 1. Immediately update frontend state (optimistic update)
get().internal_dispatchTopic(
{ type: 'addTopic', value: { ...params, id: tmpId } },
'internal_createTopic',
);
get().internal_updateTopicLoading(tmpId, true);
// 2. 调用后端服务
// 2. Call backend service
const topicId = await topicService.createTopic(params);
get().internal_updateTopicLoading(tmpId, false);
// 3. 刷新数据确保一致性
// 3. Refresh data to ensure consistency
get().internal_updateTopicLoading(topicId, true);
await get().refreshTopic();
get().internal_updateTopicLoading(topicId, false);
return topicId;
},
```
### 3. Dispatch Methods (`internal_dispatch*`)
专门处理状态更新的方法:
- 命名:`internal_dispatch` + 实体名(`internal_dispatchTopic`, `internal_dispatchMessage`
- 职责:调用 reducer、更新 Zustand store、处理状态对比
Methods dedicated to handling state updates:
- Naming: `internal_dispatch` + entity name (`internal_dispatchTopic`, `internal_dispatchMessage`)
- Responsibilities: Calling reducers, updating Zustand store, handling state comparison
```typescript
// Dispatch Method 示例
// Dispatch Method example
internal_dispatchTopic: (payload, action) => {
const nextTopics = topicReducer(topicSelectors.currentTopics(get()), payload);
const nextMap = { ...get().topicMaps, [get().activeId]: nextTopics };
if (isEqual(nextMap, get().topicMaps)) return;
set({ topicMaps: nextMap }, false, action ?? n(`dispatchTopic/${payload.type}`));
},
```
## 何时使用 Reducer 模式 vs. 简单 `set`
## When to Use Reducer Pattern vs. Simple `set`
### 使用 Reducer 模式的场景
### Use Reducer Pattern When
适用于复杂的数据结构管理,特别是:
- 管理对象列表或映射(如 `messagesMap`, `topicMaps`
- 需要乐观更新的场景
- 状态转换逻辑复杂
- 需要类型安全的 action payload
Suitable for complex data structure management, especially:
- Managing object lists or maps (e.g., `messagesMap`, `topicMaps`)
- Scenarios requiring optimistic updates
- Complex state transition logic
- Type-safe action payloads needed
```typescript
// Reducer 模式示例 - 复杂消息状态管理
// Reducer pattern example - Complex message state management
export const messagesReducer = (state: ChatMessage[], payload: MessageDispatch): ChatMessage[] => {
switch (payload.type) {
case 'updateMessage': {
return produce(state, (draftState) => {
const index = draftState.findIndex((i) => i.id === payload.id);
if (index < 0) return;
draftState[index] = merge(draftState[index], {
...payload.value,
updatedAt: Date.now()
draftState[index] = merge(draftState[index], {
...payload.value,
updatedAt: Date.now(),
});
});
}
case 'createMessage': {
return produce(state, (draftState) => {
draftState.push({
...payload.value,
id: payload.id,
createdAt: Date.now(),
updatedAt: Date.now(),
meta: {}
});
});
// ...
}
// ...其他复杂状态转换
// ...other complex state transitions
}
};
```
### 使用简单 `set` 的场景
### Use Simple `set` When
适用于简单状态更新:
- 切换布尔值
- 更新简单字符串/数字
- 设置单一状态字段
Suitable for simple state updates:
- Toggling boolean values
- Updating simple strings/numbers
- Setting single state fields
```typescript
// 简单 set 示例
// Simple set example
updateInputMessage: (message) => {
if (isEqual(message, get().inputMessage)) return;
set({ inputMessage: message }, false, n('updateInputMessage'));
@@ -142,45 +131,45 @@ togglePortal: (open?: boolean) => {
},
```
## 乐观更新实现模式
## Optimistic Update Implementation Patterns
乐观更新是 LobeChat 中的核心模式,用于提供流畅的用户体验:
Optimistic updates are a core pattern in LobeChat for providing smooth user experience:
### 标准乐观更新流程
### Standard Optimistic Update Flow
```typescript
// 完整的乐观更新示例
// Complete optimistic update example
internal_updateMessageContent: async (id, content, extra) => {
const { internal_dispatchMessage, refreshMessages } = get();
// 1. 立即更新前端状态(乐观更新)
// 1. Immediately update frontend state (optimistic update)
internal_dispatchMessage({
id,
type: 'updateMessage',
value: { content },
});
// 2. 调用后端服务
// 2. Call backend service
await messageService.updateMessage(id, {
content,
tools: extra?.toolCalls ? internal_transformToolCalls(extra.toolCalls) : undefined,
// ...其他字段
// ...other fields
});
// 3. 刷新确保数据一致性
// 3. Refresh to ensure data consistency
await refreshMessages();
},
```
### 创建操作的乐观更新
### Optimistic Update for Create Operations
```typescript
internal_createMessage: async (message, context) => {
const { internal_createTmpMessage, refreshMessages, internal_toggleMessageLoading } = get();
let tempId = context?.tempMessageId;
if (!tempId) {
// 创建临时消息用于乐观更新
// Create temporary message for optimistic update
tempId = internal_createTmpMessage(message);
internal_toggleMessageLoading(true, tempId);
}
@@ -194,7 +183,7 @@ internal_createMessage: async (message, context) => {
return id;
} catch (e) {
internal_toggleMessageLoading(false, tempId);
// 错误处理:更新消息错误状态
// Error handling: update message error state
internal_dispatchMessage({
id: tempId,
type: 'updateMessage',
@@ -204,96 +193,77 @@ internal_createMessage: async (message, context) => {
},
```
### 删除操作模式(不使用乐观更新)
### Delete Operation Pattern (No Optimistic Update)
删除操作通常不适合乐观更新,因为:
- 删除是破坏性操作,错误恢复复杂
- 用户对删除操作的即时反馈期望较低
- 删除失败时恢复原状态会造成困惑
Delete operations typically don't suit optimistic updates because:
- Deletion is destructive; error recovery is complex
- Users have lower expectations for immediate feedback on deletions
- Restoring state on deletion failure causes confusion
```typescript
// 删除操作的标准模式 - 无乐观更新
// Standard delete operation pattern - No optimistic update
removeGenerationTopic: async (id: string) => {
const { internal_removeGenerationTopic } = get();
await internal_removeGenerationTopic(id);
},
internal_removeGenerationTopic: async (id: string) => {
// 1. 显示加载状态
// 1. Show loading state
get().internal_updateGenerationTopicLoading(id, true);
try {
// 2. 直接调用后端服务
// 2. Directly call backend service
await generationTopicService.deleteTopic(id);
// 3. 刷新数据获取最新状态
// 3. Refresh data to get latest state
await get().refreshGenerationTopics();
} finally {
// 4. 确保清除加载状态(无论成功或失败)
// 4. Ensure loading state is cleared (whether success or failure)
get().internal_updateGenerationTopicLoading(id, false);
}
},
```
删除操作的特点:
- 直接调用服务,不预先更新状态
- 依赖 loading 状态提供用户反馈
- 操作完成后刷新整个列表确保一致性
- 使用 `try/finally` 确保 loading 状态总是被清理
Delete operation characteristics:
## 加载状态管理模式
- Directly call service without pre-updating state
- Rely on loading state for user feedback
- Refresh entire list after operation to ensure consistency
- Use `try/finally` to ensure loading state is always cleaned up
LobeChat 使用统一的加载状态管理模式:
## Loading State Management Pattern
### 数组式加载状态
LobeChat uses a unified loading state management pattern:
### Array-based Loading State
```typescript
// initialState.ts 中定义
// Define in initialState.ts
export interface ChatMessageState {
messageLoadingIds: string[]; // 消息加载状态
messageEditingIds: string[]; // 消息编辑状态
chatLoadingIds: string[]; // 对话生成状态
messageEditingIds: string[]; // Message editing state
}
// action 中管理
internal_toggleMessageLoading: (loading, id) => {
set({
messageLoadingIds: toggleBooleanList(get().messageLoadingIds, id, loading),
}, false, `internal_toggleMessageLoading/${loading ? 'start' : 'end'}`);
},
// Manage in action
{
toggleMessageEditing: (id, editing) => {
set(
{ messageEditingIds: toggleBooleanList(get().messageEditingIds, id, editing) },
false,
'toggleMessageEditing',
);
};
}
```
### 统一的加载状态工具
## SWR Integration Pattern
LobeChat uses SWR for data fetching and cache management:
### Hook-based Data Fetching
```typescript
// 通用的加载状态切换工具
internal_toggleLoadingArrays: (key, loading, id, action) => {
const abortControllerKey = `${key}AbortController`;
if (loading) {
const abortController = new AbortController();
set({
[abortControllerKey]: abortController,
[key]: toggleBooleanList(get()[key] as string[], id!, loading),
}, false, action);
return abortController;
} else {
set({
[abortControllerKey]: undefined,
[key]: id ? toggleBooleanList(get()[key] as string[], id, loading) : [],
}, false, action);
}
},
```
## SWR 集成模式
LobeChat 使用 SWR 进行数据获取和缓存管理:
### Hook 式数据获取
```typescript
// 在 action.ts 中定义 SWR hook
// Define SWR hook in action.ts
useFetchMessages: (enable, sessionId, activeTopicId) =>
useClientDataSWR<ChatMessage[]>(
enable ? [SWR_USE_FETCH_MESSAGES, sessionId, activeTopicId] : null,
@@ -304,57 +274,55 @@ useFetchMessages: (enable, sessionId, activeTopicId) =>
...get().messagesMap,
[messageMapKey(sessionId, activeTopicId)]: messages,
};
if (get().messagesInit && isEqual(nextMap, get().messagesMap)) return;
set({ messagesInit: true, messagesMap: nextMap }, false, n('useFetchMessages'));
},
},
),
```
### 缓存失效和刷新
### Cache Invalidation and Refresh
```typescript
// 刷新数据的标准模式
// Standard data refresh pattern
refreshMessages: async () => {
await mutate([SWR_USE_FETCH_MESSAGES, get().activeId, get().activeTopicId]);
},
refreshTopic: async () => {
return mutate([SWR_USE_FETCH_TOPIC, get().activeId]);
},
};
```
## 命名规范总结
## Naming Convention Summary
### Action 命名模式
- Public Actions: 动词形式,描述用户意图
### Action Naming Patterns
- Public Actions: Verb form, describing user intent
- `createTopic`, `sendMessage`, `regenerateMessage`
- Internal Actions: `internal_` + 动词,描述内部操作
- Internal Actions: `internal_` + verb, describing internal operation
- `internal_createTopic`, `internal_updateMessageContent`
- Dispatch Methods: `internal_dispatch` + 实体名
- Dispatch Methods: `internal_dispatch` + entity name
- `internal_dispatchTopic`, `internal_dispatchMessage`
- Toggle Methods: `internal_toggle` + 状态名
- Toggle Methods: `internal_toggle` + state name
- `internal_toggleMessageLoading`, `internal_toggleChatLoading`
### 状态命名模式
- ID 数组: `[entity]LoadingIds`, `[entity]EditingIds`
- 映射结构: `[entity]Maps`, `[entity]Map`
- 当前激活: `active[Entity]Id`
- 初始化标记: `[entity]sInit`
### State Naming Patterns
## 最佳实践
- ID arrays: `[entity]LoadingIds`, `[entity]EditingIds`
- Map structures: `[entity]Maps`, `[entity]Map`
- Currently active: `active[Entity]Id`
- Initialization flags: `[entity]sInit`
1. 合理使用乐观更新:
- ✅ 适用:创建、更新操作(用户交互频繁)
- ❌ 避免:删除操作(破坏性操作,错误恢复复杂)
2. 加载状态管理:使用统一的加载状态数组管理并发操作
3. 类型安全:为所有 action payload 定义 TypeScript 接口
4. SWR 集成:使用 SWR 管理数据获取和缓存失效
5. AbortController:为长时间运行的操作提供取消能力
6. 操作模式选择:
- 创建/更新:乐观更新 + 最终一致性
- 删除:加载状态 + 服务调用 + 数据刷新
## Best Practices
这套 Action 组织模式确保了代码的一致性、可维护性,并提供了优秀的用户体验。
1. Use optimistic updates appropriately:
- ✅ Suitable: Create, update operations (frequent user interaction)
- ❌ Avoid: Delete operations (destructive, complex error recovery)
2. Loading state management: Use unified loading state arrays to manage concurrent operations
3. Type safety: Define TypeScript interfaces for all action payloads
4. SWR integration: Use SWR to manage data fetching and cache invalidation
5. AbortController: Provide cancellation capability for long-running operations
6. Operation mode selection:
- Create/Update: Optimistic update + eventual consistency
- Delete: Loading state + service call + data refresh
This Action organization pattern ensures code consistency, maintainability, and provides excellent user experience.
+16 -8
View File
@@ -1,8 +1,9 @@
---
description:
description:
globs: src/store/**
alwaysApply: false
---
# LobeChat Zustand Store Slice 组织架构
本文档描述了 LobeChat 项目中 Zustand Store 的模块化 Slice 组织方式,展示如何通过分片架构管理复杂的应用状态。
@@ -69,7 +70,7 @@ export const useChatStore = createWithEqualityFn<ChatStore>()(
每个 slice 位于 `src/store/chat/slices/[sliceName]/` 目录下:
```
```plaintext
src/store/chat/slices/
└── [sliceName]/ # 例如 message, topic, aiChat, builtinTool
├── action.ts # 定义 actions (或者是一个 actions/ 目录)
@@ -159,15 +160,16 @@ export const topicReducer = (state: ChatTopic[] = [], payload: ChatTopicDispatch
// 典型的 selectors.ts 结构
import { ChatStoreState } from '../../initialState';
const currentTopics = (s: ChatStoreState): ChatTopic[] | undefined =>
s.topicMaps[s.activeId];
const currentTopics = (s: ChatStoreState): ChatTopic[] | undefined => s.topicMaps[s.activeId];
const currentActiveTopic = (s: ChatStoreState): ChatTopic | undefined => {
return currentTopics(s)?.find((topic) => topic.id === s.activeTopicId);
};
const getTopicById = (id: string) => (s: ChatStoreState): ChatTopic | undefined =>
currentTopics(s)?.find((topic) => topic.id === id);
const getTopicById =
(id: string) =>
(s: ChatStoreState): ChatTopic | undefined =>
currentTopics(s)?.find((topic) => topic.id === id);
// 核心模式:使用 xxxSelectors 聚合导出
export const topicSelectors = {
@@ -219,13 +221,15 @@ src/store/chat/slices/builtinTool/
## 状态设计模式
### 1. Map 结构用于关联数据
```typescript
// 以 sessionId 为 key,管理多个会话的数据
topicMaps: Record<string, ChatTopic[]>
messagesMap: Record<string, ChatMessage[]>
topicMaps: Record<string, ChatTopic[]>;
messagesMap: Record<string, ChatMessage[]>;
```
### 2. 数组用于加载状态管理
```typescript
// 管理多个并发操作的加载状态
messageLoadingIds: string[]
@@ -234,6 +238,7 @@ chatLoadingIds: string[]
```
### 3. 可选字段用于当前活动项
```typescript
// 当前激活的实体 ID
activeId: string
@@ -244,6 +249,7 @@ activeThreadId?: string
## Slice 集成到顶层 Store
### 1. 状态聚合
```typescript
// 在 initialState.ts 中
export type ChatStoreState = ChatTopicState &
@@ -253,6 +259,7 @@ export type ChatStoreState = ChatTopicState &
```
### 2. Action 接口聚合
```typescript
// 在 store.ts 中
export interface ChatStoreAction
@@ -263,6 +270,7 @@ export interface ChatStoreAction
```
### 3. Selector 统一导出
```typescript
// 在 selectors.ts 中 - 统一聚合 selectors
export { chatSelectors } from './slices/message/selectors';
+1
View File
@@ -1,5 +1,6 @@
const config = require('@lobehub/lint').eslint;
config.root = true;
config.extends.push('plugin:@next/next/recommended');
config.rules['unicorn/no-negated-condition'] = 0;
+30
View File
@@ -0,0 +1,30 @@
name: Setup Node and Bun
description: Setup Node.js and Bun for workflows
inputs:
node-version:
description: Node.js version
required: true
bun-version:
description: Bun version
required: true
package-manager-cache:
description: Pass-through to actions/setup-node package-manager-cache
required: false
default: 'false'
runs:
using: composite
steps:
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ inputs.node-version }}
package-manager-cache: ${{ inputs.package-manager-cache }}
- name: Install bun
uses: oven-sh/setup-bun@v2
with:
bun-version: ${{ inputs.bun-version }}
@@ -0,0 +1,27 @@
name: Setup Node and pnpm
description: Setup Node.js and pnpm for workflows
inputs:
node-version:
description: Node.js version
required: true
package-manager-cache:
description: Pass-through to actions/setup-node package-manager-cache
required: false
default: 'false'
runs:
using: composite
steps:
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
run_install: false
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ inputs.node-version }}
package-manager-cache: ${{ inputs.package-manager-cache }}
@@ -0,0 +1,85 @@
name: Desktop Next Build
on:
workflow_dispatch:
push:
branches:
- next
pull_request:
paths:
- 'apps/desktop/**'
- 'scripts/electronWorkflow/**'
- 'package.json'
- 'pnpm-lock.yaml'
- 'bun.lockb'
- 'src/**'
- 'packages/**'
- '.github/workflows/desktop-build-electron.yml'
concurrency:
group: desktop-electron-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
env:
NODE_VERSION: 24.11.1
BUN_VERSION: 1.2.23
jobs:
build-next:
name: Build desktop Next bundle
runs-on: ubuntu-latest
env:
NODE_OPTIONS: --max-old-space-size=6144
UPDATE_CHANNEL: nightly
NEXT_PUBLIC_DESKTOP_PROJECT_ID: ${{ secrets.UMAMI_NIGHTLY_DESKTOP_PROJECT_ID || 'dummy-desktop-project' }}
NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL: ${{ secrets.UMAMI_NIGHTLY_DESKTOP_BASE_URL || 'https://analytics.example.com' }}
steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
- name: Enable Corepack
run: corepack enable
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
run_install: false
- name: Get pnpm store directory
id: pnpm-store
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_OUTPUT
- name: Cache pnpm store
uses: actions/cache@v4
with:
path: ${{ steps.pnpm-store.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ env.NODE_VERSION }}-${{ hashFiles('pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-${{ env.NODE_VERSION }}-
${{ runner.os }}-pnpm-store-
- name: Setup bun
uses: oven-sh/setup-bun@v2
with:
bun-version: ${{ env.BUN_VERSION }}
- name: Install dependencies
run: pnpm install --node-linker=hoisted
- name: Install desktop dependencies
run: |
cd apps/desktop
bun run install-isolated
- name: Build desktop Next.js bundle
run: bun run desktop:build-electron
+341
View File
@@ -0,0 +1,341 @@
name: Desktop Manual Build
on:
workflow_dispatch:
inputs:
channel:
description: 'Release channel for desktop build (affects version suffix and workflow:set-desktop-version)'
required: true
default: nightly
type: choice
options:
- nightly
- beta
- stable
build_macos:
description: 'Build macOS artifacts'
required: true
default: true
type: boolean
build_windows:
description: 'Build Windows artifacts'
required: true
default: true
type: boolean
build_linux:
description: 'Build Linux artifacts'
required: true
default: true
type: boolean
version:
description: 'Override desktop version (e.g. 1.2.3). Leave empty to auto-generate.'
required: false
default: ''
concurrency:
group: manual-${{ github.ref }}-${{ github.workflow }}
cancel-in-progress: true
permissions:
contents: read
env:
NODE_VERSION: 24.11.1
BUN_VERSION: 1.2.23
jobs:
test:
name: Code quality check
runs-on: ubuntu-latest
steps:
- name: Checkout base
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Setup Node & Bun
uses: ./.github/actions/setup-node-bun
with:
node-version: ${{ env.NODE_VERSION }}
bun-version: ${{ env.BUN_VERSION }}
package-manager-cache: 'false'
- name: Install deps
run: bun i
env:
NODE_OPTIONS: --max-old-space-size=6144
- name: Lint
run: bun run lint
env:
NODE_OPTIONS: --max-old-space-size=6144
version:
name: Determine version
runs-on: ubuntu-latest
outputs:
version: ${{ steps.set_version.outputs.version }}
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
package-manager-cache: false
- name: Set version
id: set_version
env:
INPUT_VERSION: ${{ inputs.version }}
CHANNEL: ${{ inputs.channel }}
run: |
base_version=$(node -p "require('./apps/desktop/package.json').version")
if [ -n "$INPUT_VERSION" ]; then
version="$INPUT_VERSION"
echo "📦 Using provided version: ${version} (base: ${base_version})"
else
ci_build_number="${{ github.run_number }}"
version="0.0.0-${CHANNEL}.manual.${ci_build_number}"
echo "📦 Generated version: ${version} (base: ${base_version})"
fi
echo "version=${version}" >> $GITHUB_OUTPUT
- name: Version Summary
run: |
echo "🚦 Release Version: ${{ steps.set_version.outputs.version }}"
build-macos:
needs: [version, test]
name: Build Desktop App (macOS)
if: inputs.build_macos
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, macos-15-intel]
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Setup Node & pnpm
uses: ./.github/actions/setup-node-pnpm
with:
node-version: ${{ env.NODE_VERSION }}
package-manager-cache: 'false'
# node-linker=hoisted 模式将可以确保 asar 压缩可用
- name: Install dependencies
run: pnpm install --node-linker=hoisted
- name: Install deps on Desktop
run: npm run install-isolated --prefix=./apps/desktop
- name: Set package version
run: npm run workflow:set-desktop-version ${{ needs.version.outputs.version }} ${{ inputs.channel }}
- name: Build artifact on macOS
run: npm run desktop:build
env:
UPDATE_CHANNEL: ${{ inputs.channel }}
APP_URL: http://localhost:3015
DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
CSC_LINK: ${{ secrets.APPLE_CERTIFICATE_BASE64 }}
CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
NEXT_PUBLIC_DESKTOP_PROJECT_ID: ${{ inputs.channel == 'beta' && secrets.UMAMI_BETA_DESKTOP_PROJECT_ID || secrets.UMAMI_NIGHTLY_DESKTOP_PROJECT_ID }}
NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL: ${{ inputs.channel == 'beta' && secrets.UMAMI_BETA_DESKTOP_BASE_URL || secrets.UMAMI_NIGHTLY_DESKTOP_BASE_URL }}
CSC_FOR_PULL_REQUEST: true
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
- name: Rename macOS latest-mac.yml for multi-architecture support
if: runner.os == 'macOS'
run: |
cd apps/desktop/release
if [ -f "latest-mac.yml" ]; then
SYSTEM_ARCH=$(uname -m)
if [[ "$SYSTEM_ARCH" == "arm64" ]]; then
ARCH_SUFFIX="arm64"
else
ARCH_SUFFIX="x64"
fi
mv latest-mac.yml "latest-mac-${ARCH_SUFFIX}.yml"
echo "✅ Renamed latest-mac.yml to latest-mac-${ARCH_SUFFIX}.yml (detected: $SYSTEM_ARCH)"
ls -la latest-mac-*.yml
else
echo "⚠️ latest-mac.yml not found, skipping rename"
ls -la latest*.yml || echo "No latest*.yml files found"
fi
- name: Upload artifact
uses: actions/upload-artifact@v5
with:
name: release-${{ matrix.os }}
path: |
apps/desktop/release/latest*
apps/desktop/release/*.dmg*
apps/desktop/release/*.zip*
apps/desktop/release/*.exe*
apps/desktop/release/*.AppImage
apps/desktop/release/*.deb*
apps/desktop/release/*.snap*
apps/desktop/release/*.rpm*
apps/desktop/release/*.tar.gz*
retention-days: 5
build-windows:
needs: [version, test]
name: Build Desktop App (Windows)
if: inputs.build_windows
runs-on: windows-2025
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Setup Node & pnpm
uses: ./.github/actions/setup-node-pnpm
with:
node-version: ${{ env.NODE_VERSION }}
package-manager-cache: 'false'
- name: Install dependencies
run: pnpm install --node-linker=hoisted
- name: Install deps on Desktop
run: npm run install-isolated --prefix=./apps/desktop
- name: Set package version
run: npm run workflow:set-desktop-version ${{ needs.version.outputs.version }} ${{ inputs.channel }}
- name: Build artifact on Windows
run: npm run desktop:build
env:
UPDATE_CHANNEL: ${{ inputs.channel }}
APP_URL: http://localhost:3015
DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
NEXT_PUBLIC_DESKTOP_PROJECT_ID: ${{ inputs.channel == 'beta' && secrets.UMAMI_BETA_DESKTOP_PROJECT_ID || secrets.UMAMI_NIGHTLY_DESKTOP_PROJECT_ID }}
NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL: ${{ inputs.channel == 'beta' && secrets.UMAMI_BETA_DESKTOP_BASE_URL || secrets.UMAMI_NIGHTLY_DESKTOP_BASE_URL }}
TEMP: C:\temp
TMP: C:\temp
- name: Upload artifact
uses: actions/upload-artifact@v5
with:
name: release-windows-2025
path: |
apps/desktop/release/latest*
apps/desktop/release/*.dmg*
apps/desktop/release/*.zip*
apps/desktop/release/*.exe*
apps/desktop/release/*.AppImage
apps/desktop/release/*.deb*
apps/desktop/release/*.snap*
apps/desktop/release/*.rpm*
apps/desktop/release/*.tar.gz*
retention-days: 5
build-linux:
needs: [version, test]
name: Build Desktop App (Linux)
if: inputs.build_linux
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Setup Node & pnpm
uses: ./.github/actions/setup-node-pnpm
with:
node-version: ${{ env.NODE_VERSION }}
package-manager-cache: 'false'
- name: Install dependencies
run: pnpm install --node-linker=hoisted
- name: Install deps on Desktop
run: npm run install-isolated --prefix=./apps/desktop
- name: Set package version
run: npm run workflow:set-desktop-version ${{ needs.version.outputs.version }} ${{ inputs.channel }}
- name: Build artifact on Linux
run: npm run desktop:build
env:
UPDATE_CHANNEL: ${{ inputs.channel }}
APP_URL: http://localhost:3015
DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
NEXT_PUBLIC_DESKTOP_PROJECT_ID: ${{ inputs.channel == 'beta' && secrets.UMAMI_BETA_DESKTOP_PROJECT_ID || secrets.UMAMI_NIGHTLY_DESKTOP_PROJECT_ID }}
NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL: ${{ inputs.channel == 'beta' && secrets.UMAMI_BETA_DESKTOP_BASE_URL || secrets.UMAMI_NIGHTLY_DESKTOP_BASE_URL }}
- name: Upload artifact
uses: actions/upload-artifact@v5
with:
name: release-ubuntu-latest
path: |
apps/desktop/release/latest*
apps/desktop/release/*.dmg*
apps/desktop/release/*.zip*
apps/desktop/release/*.exe*
apps/desktop/release/*.AppImage
apps/desktop/release/*.deb*
apps/desktop/release/*.snap*
apps/desktop/release/*.rpm*
apps/desktop/release/*.tar.gz*
retention-days: 5
merge-mac-files:
needs: [build-macos, version]
name: Merge macOS Release Files
runs-on: ubuntu-latest
permissions:
contents: read
if: inputs.build_macos
steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Setup Node & Bun
uses: ./.github/actions/setup-node-bun
with:
node-version: ${{ env.NODE_VERSION }}
bun-version: ${{ env.BUN_VERSION }}
package-manager-cache: 'false'
- name: Download artifacts
uses: actions/download-artifact@v6
with:
path: release
pattern: release-*
merge-multiple: true
- name: List downloaded artifacts
run: ls -R release
- name: Install yaml only for merge step
run: |
cd scripts/electronWorkflow
if [ ! -f package.json ]; then
echo '{"name":"merge-mac-release","private":true}' > package.json
fi
bun add --no-save yaml@2.8.1
- name: Merge latest-mac.yml files
run: bun run scripts/electronWorkflow/mergeMacReleaseFiles.js
- name: Upload artifacts with merged macOS files
uses: actions/upload-artifact@v5
with:
name: merged-release-manual
path: release/
retention-days: 1
+18 -31
View File
@@ -29,16 +29,12 @@ jobs:
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v6
- name: Setup Node & Bun
uses: ./.github/actions/setup-node-bun
with:
node-version: 24.11.1
package-manager-cache: false
- name: Install bun
uses: oven-sh/setup-bun@v2
with:
bun-version: 1.2.23
package-manager-cache: 'false'
- name: Install deps
run: bun i
@@ -103,16 +99,11 @@ jobs:
with:
fetch-depth: 0
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
run_install: false
- name: Setup Node.js
uses: actions/setup-node@v6
- name: Setup Node & pnpm
uses: ./.github/actions/setup-node-pnpm
with:
node-version: 24.11.1
package-manager-cache: false
package-manager-cache: 'false'
# node-linker=hoisted 模式将可以确保 asar 压缩可用
- name: Install dependencies
@@ -132,11 +123,11 @@ jobs:
run: npm run desktop:build
env:
# 设置更新通道,PR构建为nightly,否则为stable
UPDATE_CHANNEL: "nightly"
UPDATE_CHANNEL: 'nightly'
APP_URL: http://localhost:3015
DATABASE_URL: "postgresql://postgres@localhost:5432/postgres"
DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
# 默认添加一个加密 SECRET
KEY_VAULTS_SECRET: "oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE="
KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
# macOS 签名和公证配置(fork 的 PR 访问不到 secrets,会跳过签名)
CSC_LINK: ${{ secrets.APPLE_CERTIFICATE_BASE64 }}
CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
@@ -156,10 +147,10 @@ jobs:
run: npm run desktop:build
env:
# 设置更新通道,PR构建为nightly,否则为stable
UPDATE_CHANNEL: "nightly"
UPDATE_CHANNEL: 'nightly'
APP_URL: http://localhost:3015
DATABASE_URL: "postgresql://postgres@localhost:5432/postgres"
KEY_VAULTS_SECRET: "oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE="
DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
NEXT_PUBLIC_DESKTOP_PROJECT_ID: ${{ secrets.UMAMI_NIGHTLY_DESKTOP_PROJECT_ID }}
NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL: ${{ secrets.UMAMI_NIGHTLY_DESKTOP_BASE_URL }}
# 将 TEMP 和 TMP 目录设置到 C 盘
@@ -172,10 +163,10 @@ jobs:
run: npm run desktop:build
env:
# 设置更新通道,PR构建为nightly,否则为stable
UPDATE_CHANNEL: "nightly"
UPDATE_CHANNEL: 'nightly'
APP_URL: http://localhost:3015
DATABASE_URL: "postgresql://postgres@localhost:5432/postgres"
KEY_VAULTS_SECRET: "oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE="
DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
NEXT_PUBLIC_DESKTOP_PROJECT_ID: ${{ secrets.UMAMI_NIGHTLY_DESKTOP_PROJECT_ID }}
NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL: ${{ secrets.UMAMI_NIGHTLY_DESKTOP_BASE_URL }}
@@ -229,16 +220,12 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v5
- name: Setup Node.js
uses: actions/setup-node@v6
- name: Setup Node & Bun
uses: ./.github/actions/setup-node-bun
with:
node-version: 24.11.1
package-manager-cache: false
- name: Install bun
uses: oven-sh/setup-bun@v2
with:
bun-version: 1.2.23
package-manager-cache: 'false'
# 下载所有平台的构建产物
- name: Download artifacts
+1 -1
View File
@@ -146,7 +146,7 @@ jobs:
NODE_OPTIONS: --max-old-space-size=6144
- name: Typecheck Desktop
run: pnpm typecheck
run: pnpm type-check
working-directory: apps/desktop
- name: Test Desktop Client
+3 -3
View File
@@ -24,7 +24,7 @@ Desktop.ini
.windsurfrules
*.code-workspace
.vscode/sessions.json
prd
# Temporary files
.temp/
temp/
@@ -93,7 +93,6 @@ robots.txt
.husky/prepare-commit-msg
# Documents and media
*.patch
*.pdf
# Cloud service keys
@@ -114,5 +113,6 @@ CLAUDE.local.md
*.ppt*
*.doc*
*.xls*
e2e/reports
out
i18n-unused-keys-report.json
+3 -1
View File
@@ -30,7 +30,9 @@ module.exports = defineConfig({
jsonMode: true,
},
markdown: {
reference: '你需要保持 mdx 的组件格式,输出文本不需要在最外层包裹任何代码块语法',
reference:
'你需要保持 mdx 的组件格式,输出文本不需要在最外层包裹任何代码块语法。以下是一些词汇的固定翻译:\n' +
JSON.stringify(require('./glossary.json'), null, 2),
entry: ['./README.zh-CN.md', './contributing/**/*.zh-CN.md', './docs/**/*.zh-CN.mdx'],
entryLocale: 'zh-CN',
outputLocales: ['en-US'],
+3 -2
View File
@@ -26,6 +26,7 @@ The project follows a well-organized monorepo structure:
- `src/` - Main source code
- `docs/` - Documentation
- `.cursor/rules/` - Development rules and guidelines
- PR titles starting with `✨ feat/` or `🐛 fix` will trigger the release workflow upon merge. Only use these prefixes for significant user-facing feature changes or bug fixes
## Development Workflow
@@ -83,10 +84,10 @@ All following rules are saved under `.cursor/rules/` directory:
### Frontend
- `react-component.mdc` React component style guide and conventions
- `react.mdc` React component style guide and conventions
- `i18n.mdc` Internationalization guide using react-i18next
- `typescript.mdc` TypeScript code style guide
- `packages/react-layout-kit.mdc` Usage guide for react-layout-kit
- `packages/react-layout-kit.mdc` Usage guide for Flexbox and Center components from @lobehub/ui
### State Management
+336
View File
@@ -2,6 +2,342 @@
# Changelog
## [Version 2.0.0-next.176](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.175...v2.0.0-next.176)
<sup>Released on **2025-12-23**</sup>
#### ✨ Features
- **misc**: Mobile native better auth support.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### What's improved
- **misc**: Mobile native better auth support, closes [#10871](https://github.com/lobehub/lobe-chat/issues/10871) ([8c42a93](https://github.com/lobehub/lobe-chat/commit/8c42a93))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
## [Version 2.0.0-next.175](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.174...v2.0.0-next.175)
<sup>Released on **2025-12-21**</sup>
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
## [Version 2.0.0-next.174](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.173...v2.0.0-next.174)
<sup>Released on **2025-12-20**</sup>
#### ♻ Code Refactoring
- **misc**: Refactor database schema.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### Code refactoring
- **misc**: Refactor database schema, closes [#10860](https://github.com/lobehub/lobe-chat/issues/10860) ([5c489bc](https://github.com/lobehub/lobe-chat/commit/5c489bc))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
## [Version 2.0.0-next.173](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.172...v2.0.0-next.173)
<sup>Released on **2025-12-16**</sup>
#### 🐛 Bug Fixes
- **misc**: Request to gpt5 series should not with `top_p`, temperature when reasoning effort is not none.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### What's fixed
- **misc**: Request to gpt5 series should not with `top_p`, temperature when reasoning effort is not none, closes [#10800](https://github.com/lobehub/lobe-chat/issues/10800) ([b4ad470](https://github.com/lobehub/lobe-chat/commit/b4ad470))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
## [Version 2.0.0-next.172](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.171...v2.0.0-next.172)
<sup>Released on **2025-12-15**</sup>
#### 💄 Styles
- **misc**: Update i18n.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### Styles
- **misc**: Update i18n, closes [#10759](https://github.com/lobehub/lobe-chat/issues/10759) ([24cae77](https://github.com/lobehub/lobe-chat/commit/24cae77))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
## [Version 2.0.0-next.171](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.170...v2.0.0-next.171)
<sup>Released on **2025-12-14**</sup>
#### 💄 Styles
- **misc**: Update GPT-5.2 models.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### Styles
- **misc**: Update GPT-5.2 models, closes [#10749](https://github.com/lobehub/lobe-chat/issues/10749) ([0446127](https://github.com/lobehub/lobe-chat/commit/0446127))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
## [Version 2.0.0-next.170](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.169...v2.0.0-next.170)
<sup>Released on **2025-12-12**</sup>
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
## [Version 2.0.0-next.169](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.168...v2.0.0-next.169)
<sup>Released on **2025-12-12**</sup>
#### 🐛 Bug Fixes
- **misc**: Fix CVE errors.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### What's fixed
- **misc**: Fix CVE errors, closes [#10748](https://github.com/lobehub/lobe-chat/issues/10748) ([6591f3c](https://github.com/lobehub/lobe-chat/commit/6591f3c))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
## [Version 2.0.0-next.168](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.167...v2.0.0-next.168)
<sup>Released on **2025-12-12**</sup>
#### 🐛 Bug Fixes
- **misc**: Slove market oidc error.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### What's fixed
- **misc**: Slove market oidc error, closes [#10715](https://github.com/lobehub/lobe-chat/issues/10715) ([108d2a7](https://github.com/lobehub/lobe-chat/commit/108d2a7))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
## [Version 2.0.0-next.167](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.166...v2.0.0-next.167)
<sup>Released on **2025-12-11**</sup>
#### ✨ Features
- **misc**: Add Replicate image provider.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### What's improved
- **misc**: Add Replicate image provider ([542f4d9](https://github.com/lobehub/lobe-chat/commit/542f4d9))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
## [Version 2.0.0-next.166](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.165...v2.0.0-next.166)
<sup>Released on **2025-12-09**</sup>
#### 🐛 Bug Fixes
- **Dockerfile**: Electron main typing pkg.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### What's fixed
- **Dockerfile**: Electron main typing pkg, closes [#10693](https://github.com/lobehub/lobe-chat/issues/10693) ([f3357b0](https://github.com/lobehub/lobe-chat/commit/f3357b0))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
## [Version 2.0.0-next.165](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.164...v2.0.0-next.165)
<sup>Released on **2025-12-09**</sup>
#### ♻ Code Refactoring
- **electron-main**: Client ipc decorate.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### Code refactoring
- **electron-main**: Client ipc decorate, closes [#10679](https://github.com/lobehub/lobe-chat/issues/10679) ([f74befa](https://github.com/lobehub/lobe-chat/commit/f74befa))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
## [Version 2.0.0-next.164](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.163...v2.0.0-next.164)
<sup>Released on **2025-12-08**</sup>
#### 💄 Styles
- **profile**: Add mobile responsive layout and signup improvements.
- **misc**: Update link handling in PlanTag component to use react-router-dom.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### Styles
- **profile**: Add mobile responsive layout and signup improvements, closes [#10669](https://github.com/lobehub/lobe-chat/issues/10669) ([1afd471](https://github.com/lobehub/lobe-chat/commit/1afd471))
- **misc**: Update link handling in PlanTag component to use react-router-dom, closes [#10673](https://github.com/lobehub/lobe-chat/issues/10673) ([3aceeb6](https://github.com/lobehub/lobe-chat/commit/3aceeb6))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
## [Version 2.0.0-next.163](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.162...v2.0.0-next.163)
<sup>Released on **2025-12-06**</sup>
#### 🐛 Bug Fixes
- **misc**: Add smooth scroll to top on 'More' button click in Title component.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### What's fixed
- **misc**: Add smooth scroll to top on 'More' button click in Title component, closes [#10178](https://github.com/lobehub/lobe-chat/issues/10178) ([5ad4f0c](https://github.com/lobehub/lobe-chat/commit/5ad4f0c))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
## [Version 2.0.0-next.162](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.161...v2.0.0-next.162)
<sup>Released on **2025-12-05**</sup>
+9 -2
View File
@@ -17,8 +17,9 @@ read @.cursor/rules/project-structure.mdc
- The current release branch is `next` instead of `main` until v2.0.0 is officially released
- use rebase for git pull
- git commit message should prefix with gitmoji
- git branch name format example: tj/feat/feature-name
- git branch name format template: <type>/<feature-name>
- use .github/PULL_REQUEST_TEMPLATE.md to generate pull request description
- PR titles starting with `✨ feat/` or `🐛 fix` will trigger the release workflow upon merge. Only use these prefixes for significant user-facing feature changes or bug fixes
### Package Management
@@ -44,6 +45,8 @@ see @.cursor/rules/typescript.mdc
- wrap the file path in single quotes to avoid shell expansion
- Never run `bun run test` etc to run tests, this will run all tests and cost about 10mins
- If trying to fix the same test twice, but still failed, stop and ask for help.
- **Prefer `vi.spyOn` over `vi.mock`**: When mocking modules or functions, prefer using `vi.spyOn` to mock specific functions rather than `vi.mock` to mock entire modules. This approach is more targeted, easier to maintain, and allows for better control over mock behavior in individual tests.
- **Tests must pass type check**: After writing or modifying tests, run `bun run type-check` to ensure there are no type errors. Tests should pass both runtime execution and TypeScript type checking.
### Typecheck
@@ -55,7 +58,7 @@ see @.cursor/rules/typescript.mdc
- **Dev**: Translate `locales/zh-CN/namespace.json` and `locales/en-US/namespace.json` locales file only for dev preview
- DON'T run `pnpm i18n`, let CI auto handle it
## Linear Issue Management
## Linear Issue Management (ignore if not installed linear mcp)
When working with Linear issues:
@@ -64,6 +67,10 @@ When working with Linear issues:
3. **Update issue status** when completing tasks using `mcp__linear-server__update_issue`
4. **MUST add completion comment** using `mcp__linear-server__create_comment`
### Creating Issues
When creating new Linear issues using `mcp__linear-server__create_issue`, **MUST add the `claude code` label** to indicate the issue was created by Claude Code.
### Completion Comment (REQUIRED)
**Every time you complete an issue, you MUST add a comment summarizing the work done.** This is critical for:
+58 -51
View File
@@ -8,29 +8,24 @@ ARG USE_CN_MIRROR
ENV DEBIAN_FRONTEND="noninteractive"
RUN \
# If you want to build docker in China, build with --build-arg USE_CN_MIRROR=true
if [ "${USE_CN_MIRROR:-false}" = "true" ]; then \
sed -i "s/deb.debian.org/mirrors.ustc.edu.cn/g" "/etc/apt/sources.list.d/debian.sources"; \
fi \
# Add required package
&& apt update \
&& apt install ca-certificates proxychains-ng -qy \
# Prepare required package to distroless
&& mkdir -p /distroless/bin /distroless/etc /distroless/etc/ssl/certs /distroless/lib \
# Copy proxychains to distroless
&& cp /usr/lib/$(arch)-linux-gnu/libproxychains.so.4 /distroless/lib/libproxychains.so.4 \
&& cp /usr/lib/$(arch)-linux-gnu/libdl.so.2 /distroless/lib/libdl.so.2 \
&& cp /usr/bin/proxychains4 /distroless/bin/proxychains \
&& cp /etc/proxychains4.conf /distroless/etc/proxychains4.conf \
# Copy node to distroless
&& cp /usr/lib/$(arch)-linux-gnu/libstdc++.so.6 /distroless/lib/libstdc++.so.6 \
&& cp /usr/lib/$(arch)-linux-gnu/libgcc_s.so.1 /distroless/lib/libgcc_s.so.1 \
&& cp /usr/local/bin/node /distroless/bin/node \
# Copy CA certificates to distroless
&& cp /etc/ssl/certs/ca-certificates.crt /distroless/etc/ssl/certs/ca-certificates.crt \
# Cleanup temp files
&& rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/*
RUN <<'EOF'
set -e
if [ "${USE_CN_MIRROR:-false}" = "true" ]; then
sed -i "s/deb.debian.org/mirrors.ustc.edu.cn/g" "/etc/apt/sources.list.d/debian.sources"
fi
apt update
apt install ca-certificates proxychains-ng -qy
mkdir -p /distroless/bin /distroless/etc /distroless/etc/ssl/certs /distroless/lib
cp /usr/lib/$(arch)-linux-gnu/libproxychains.so.4 /distroless/lib/libproxychains.so.4
cp /usr/lib/$(arch)-linux-gnu/libdl.so.2 /distroless/lib/libdl.so.2
cp /usr/bin/proxychains4 /distroless/bin/proxychains
cp /etc/proxychains4.conf /distroless/etc/proxychains4.conf
cp /usr/lib/$(arch)-linux-gnu/libstdc++.so.6 /distroless/lib/libstdc++.so.6
cp /usr/lib/$(arch)-linux-gnu/libgcc_s.so.1 /distroless/lib/libgcc_s.so.1
cp /usr/local/bin/node /distroless/bin/node
cp /etc/ssl/certs/ca-certificates.crt /distroless/etc/ssl/certs/ca-certificates.crt
rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/*
EOF
## Builder image, install all the dependencies and build the app
FROM base AS builder
@@ -86,35 +81,45 @@ WORKDIR /app
COPY package.json pnpm-workspace.yaml ./
COPY .npmrc ./
COPY packages ./packages
# bring in desktop workspace manifest so pnpm can resolve it
COPY apps/desktop/src/main/package.json ./apps/desktop/src/main/package.json
RUN \
# If you want to build docker in China, build with --build-arg USE_CN_MIRROR=true
if [ "${USE_CN_MIRROR:-false}" = "true" ]; then \
export SENTRYCLI_CDNURL="https://npmmirror.com/mirrors/sentry-cli"; \
npm config set registry "https://registry.npmmirror.com/"; \
echo 'canvas_binary_host_mirror=https://npmmirror.com/mirrors/canvas' >> .npmrc; \
fi \
# Set the registry for corepack
&& export COREPACK_NPM_REGISTRY=$(npm config get registry | sed 's/\/$//') \
# Update corepack to latest (nodejs/corepack#612)
&& npm i -g corepack@latest \
# Enable corepack
&& corepack enable \
# Use pnpm for corepack
&& corepack use $(sed -n 's/.*"packageManager": "\(.*\)".*/\1/p' package.json) \
# Install the dependencies
&& pnpm i \
# Add db migration dependencies
&& mkdir -p /deps \
&& cd /deps \
&& pnpm init \
&& pnpm add pg drizzle-orm
RUN <<'EOF'
set -e
if [ "${USE_CN_MIRROR:-false}" = "true" ]; then
export SENTRYCLI_CDNURL="https://npmmirror.com/mirrors/sentry-cli"
npm config set registry "https://registry.npmmirror.com/"
echo 'canvas_binary_host_mirror=https://npmmirror.com/mirrors/canvas' >> .npmrc
fi
export COREPACK_NPM_REGISTRY=$(npm config get registry | sed 's/\/$//')
npm i -g corepack@latest
corepack enable
corepack use $(sed -n 's/.*"packageManager": "\(.*\)".*/\1/p' package.json)
pnpm i
mkdir -p /deps
cd /deps
pnpm init
pnpm add pg drizzle-orm
EOF
COPY . .
# run build standalone for docker version
RUN npm run build:docker
# Prepare desktop export assets for Electron packaging (if generated)
RUN <<'EOF'
set -e
if [ -d "/app/out" ]; then
mkdir -p /app/apps/desktop/dist/next
cp -a /app/out/. /app/apps/desktop/dist/next/
echo "✅ Copied Next export output into /app/apps/desktop/dist/next"
else
echo "️ No Next export output found at /app/out, creating empty directory"
mkdir -p /app/apps/desktop/dist/next
fi
EOF
## Application image, copy all the files for production
FROM busybox:latest AS app
@@ -123,6 +128,8 @@ COPY --from=base /distroless/ /
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder /app/.next/standalone /app/
# Copy Next export output for desktop renderer
COPY --from=builder /app/apps/desktop/dist/next /app/apps/desktop/dist/next
# Copy database migrations
COPY --from=builder /app/packages/database/migrations /app/migrations
@@ -137,12 +144,12 @@ COPY --from=builder /deps/node_modules/drizzle-orm /app/node_modules/drizzle-orm
# Copy server launcher
COPY --from=builder /app/scripts/serverLauncher/startServer.js /app/startServer.js
RUN \
# Add nextjs:nodejs to run the app
addgroup -S -g 1001 nodejs \
&& adduser -D -G nodejs -H -S -h /app -u 1001 nextjs \
# Set permission for nextjs:nodejs
&& chown -R nextjs:nodejs /app /etc/proxychains4.conf
RUN <<'EOF'
set -e
addgroup -S -g 1001 nodejs
adduser -D -G nodejs -H -S -h /app -u 1001 nextjs
chown -R nextjs:nodejs /app /etc/proxychains4.conf
EOF
## Production image, copy all the files and run next
FROM scratch
+2 -1
View File
@@ -16,8 +16,9 @@ read @.cursor/rules/project-structure.mdc
- use rebase for git pull
- git commit message should prefix with gitmoji
- git branch name format example: tj/feat/feature-name
- git branch name format template: <type>/<feature-name>
- use .github/PULL_REQUEST_TEMPLATE.md to generate pull request description
- PR titles starting with `✨ feat/` or `🐛 fix` will trigger the release workflow upon merge. Only use these prefixes for significant user-facing feature changes or bug fixes
### Package Management
+10 -10
View File
@@ -345,14 +345,14 @@ In addition, these plugins are not limited to news aggregation, but can also ext
<!-- PLUGIN LIST -->
| Recent Submits | Description |
| -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| [PortfolioMeta](https://lobechat.com/discover/plugin/StockData)<br/><sup>By **portfoliometa** on **2025-11-28**</sup> | Analyze stocks and get comprehensive real-time investment data and analytics.<br/>`stock` |
| [SEO](https://lobechat.com/discover/plugin/SEO)<br/><sup>By **orrenprunckun** on **2025-11-14**</sup> | Enter any URL and keyword and get an On-Page SEO analysis & insights!<br/>`seo` |
| [Shopping tools](https://lobechat.com/discover/plugin/ShoppingTools)<br/><sup>By **shoppingtools** on **2025-10-27**</sup> | Search for products on eBay & AliExpress, find eBay events & coupons. Get prompt examples.<br/>`shopping` `e-bay` `ali-express` `coupons` |
| [Web](https://lobechat.com/discover/plugin/web)<br/><sup>By **Proghit** on **2025-01-24**</sup> | Smart web search that reads and analyzes pages to deliver comprehensive answers from Google results.<br/>`web` `search` |
| Recent Submits | Description |
| -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| [Shopping tools](https://lobechat.com/discover/plugin/ShoppingTools)<br/><sup>By **shoppingtools** on **2025-12-17**</sup> | Search for products on eBay & AliExpress, find eBay events & coupons. Get prompt examples.<br/>`shopping` `e-bay` `ali-express` `coupons` |
| [SEO Assistant](https://lobechat.com/discover/plugin/seo_assistant)<br/><sup>By **webfx** on **2025-12-17**</sup> | The SEO Assistant can generate search engine keyword information in order to aid the creation of content.<br/>`seo` `keyword` |
| [Video Captions](https://lobechat.com/discover/plugin/VideoCaptions)<br/><sup>By **maila** on **2025-12-13**</sup> | Convert Youtube links into transcribed text, enable asking questions, create chapters, and summarize its content.<br/>`video-to-text` `youtube` |
| [WeatherGPT](https://lobechat.com/discover/plugin/WeatherGPT)<br/><sup>By **steven-tey** on **2025-12-13**</sup> | Get current weather information for a specific location.<br/>`weather` |
> 📊 Total plugins: [<kbd>**41**</kbd>](https://lobechat.com/discover/plugins)
> 📊 Total plugins: [<kbd>**40**</kbd>](https://lobechat.com/discover/plugins)
<!-- PLUGIN LIST -->
@@ -387,8 +387,8 @@ Our marketplace is not just a showcase platform but also a collaborative space.
| Recent Submits | Description |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [Turtle Soup Host](https://lobechat.com/discover/assistant/lateral-thinking-puzzle)<br/><sup>By **[CSY2022](https://github.com/CSY2022)** on **2025-06-19**</sup> | A turtle soup host needs to provide the scenario, the complete story (truth of the event), and the key point (the condition for guessing correctly).<br/>`turtle-soup` `reasoning` `interaction` `puzzle` `role-playing` |
| [Gourmet Reviewer🍟](https://lobechat.com/discover/assistant/food-reviewer)<br/><sup>By **[renhai-lab](https://github.com/renhai-lab)** on **2025-06-17**</sup> | Food critique expert<br/>`gourmet` `review` `writing` |
| [Academic Writing Assistant](https://lobechat.com/discover/assistant/academic-writing-assistant)<br/><sup>By **[swarfte](https://github.com/swarfte)** on **2025-06-17**</sup> | Expert in academic research paper writing and formal documentation<br/>`academic-writing` `research` `formal-style` |
| [Gourmet Reviewer🍟](https://lobechat.com/discover/assistant/food-reviewer)<br/><sup>By **[renhai-lab](https://github.com/renhai-lab)** on **2025-06-17**</sup> | Food critique expert<br/>`gourmet` `review` `writing` |
| [Minecraft Senior Developer](https://lobechat.com/discover/assistant/java-development)<br/><sup>By **[iamyuuk](https://github.com/iamyuuk)** on **2025-06-17**</sup> | Expert in advanced Java development and Minecraft mod and server plugin development<br/>`development` `programming` `minecraft` `java` |
> 📊 Total agents: [<kbd>**505**</kbd> ](https://lobechat.com/discover/assistants)
@@ -820,7 +820,7 @@ This project is [LobeHub Community License](./LICENSE) licensed.
[docker-size-link]: https://hub.docker.com/r/lobehub/lobe-chat-database
[docker-size-shield]: https://img.shields.io/docker/image-size/lobehub/lobe-chat-database?color=369eff&labelColor=black&style=flat-square&sort=semver
[docs]: https://lobehub.com/docs/usage/start
[docs-dev-guide]: https://github.com/lobehub/lobe-chat/wiki/index
[docs-dev-guide]: https://lobehub.com/docs/development/start
[docs-docker]: https://lobehub.com/docs/self-hosting/server-database/docker-compose
[docs-env-var]: https://lobehub.com/docs/self-hosting/environment-variables
[docs-feat-agent]: https://lobehub.com/docs/usage/features/agent-market
@@ -840,7 +840,7 @@ This project is [LobeHub Community License](./LICENSE) licensed.
[docs-feat-tts]: https://lobehub.com/docs/usage/features/tts
[docs-feat-vision]: https://lobehub.com/docs/usage/features/vision
[docs-function-call]: https://lobehub.com/blog/openai-function-call
[docs-lighthouse]: https://github.com/lobehub/lobe-chat/wiki/Lighthouse
[docs-lighthouse]: https://lobehub.com/docs/development/others/lighthouse
[docs-plugin-dev]: https://lobehub.com/docs/usage/plugins/development
[docs-self-hosting]: https://lobehub.com/docs/self-hosting/start
[docs-upstream-sync]: https://lobehub.com/docs/self-hosting/advanced/upstream-sync
+13 -13
View File
@@ -12,7 +12,7 @@
<h1>Lobe Chat</h1>
现代化设计的开源 ChatGPT/LLMs 聊天应用与开发框架<br/>
支持语音合成、多模态、可扩展的([function call][docs-functionc-call])插件系统<br/>
支持语音合成、多模态、可扩展的([function call][docs-function-call])插件系统<br/>
一键**免费**拥有你自己的 ChatGPT/Gemini/Claude/Ollama 应用
[English](./README.md) · **简体中文** · [官网][official-site] · [更新日志][changelog] · [文档][docs] · [博客][blog] · [反馈问题][github-issues-link]
@@ -338,14 +338,14 @@ LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地
<!-- PLUGIN LIST -->
| 最近新增 | 描述 |
| --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| [PortfolioMeta](https://lobechat.com/discover/plugin/StockData)<br/><sup>By **portfoliometa** on **2025-11-28**</sup> | 分析股票并获取全面的实时投资数据和分析。<br/>`股票` |
| [SEO](https://lobechat.com/discover/plugin/SEO)<br/><sup>By **orrenprunckun** on **2025-11-14**</sup> | 输入任何 URL 和关键词,获取页面 SEO 分析和见解!<br/>`seo` |
| [购物工具](https://lobechat.com/discover/plugin/ShoppingTools)<br/><sup>By **shoppingtools** on **2025-10-27**</sup> | 在 eBay 和 AliExpress 上搜索产品,查找 eBay 活动和优惠券。获取快速示例。<br/>`购物` `e-bay` `ali-express` `优惠券` |
| [网页](https://lobechat.com/discover/plugin/web)<br/><sup>By **Proghit** on **2025-01-24**</sup> | 智能网页搜索,读取和分析页面,以提供来自 Google 结果的全面答案。<br/>`网页` `搜索` |
| 最近新增 | 描述 |
| -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| [购物工具](https://lobechat.com/discover/plugin/ShoppingTools)<br/><sup>By **shoppingtools** on **2025-12-17**</sup> | 在 eBay 和 AliExpress 上搜索产品,查找 eBay 活动和优惠券。获取快速示例。<br/>`购物` `e-bay` `ali-express` `优惠券` |
| [SEO 助手](https://lobechat.com/discover/plugin/seo_assistant)<br/><sup>By **webfx** on **2025-12-17**</sup> | SEO 助手可以生成搜索引擎关键词信息,以帮助创建内容。<br/>`seo` `关键词` |
| [视频字幕](https://lobechat.com/discover/plugin/VideoCaptions)<br/><sup>By **maila** on **2025-12-13**</sup> | 将 Youtube 链接转换为转录文本,使其能够提问,创建章节,并总结其内容。<br/>`视频转文字` `you-tube` |
| [天气 GPT](https://lobechat.com/discover/plugin/WeatherGPT)<br/><sup>By **steven-tey** on **2025-12-13**</sup> | 获取特定位置的当前天气信息。<br/>`天气` |
> 📊 Total plugins: [<kbd>**41**</kbd>](https://lobechat.com/discover/plugins)
> 📊 Total plugins: [<kbd>**40**</kbd>](https://lobechat.com/discover/plugins)
<!-- PLUGIN LIST -->
@@ -376,8 +376,8 @@ LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地
| 最近新增 | 描述 |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| [海龟汤主持人](https://lobechat.com/discover/assistant/lateral-thinking-puzzle)<br/><sup>By **[CSY2022](https://github.com/CSY2022)** on **2025-06-19**</sup> | 一个海龟汤主持人,需要自己提供汤面,汤底与关键点(猜中的判定条件)。<br/>`海龟汤` `推理` `互动` `谜题` `角色扮演` |
| [美食评论员🍟](https://lobechat.com/discover/assistant/food-reviewer)<br/><sup>By **[renhai-lab](https://github.com/renhai-lab)** on **2025-06-17**</sup> | 美食评价专家<br/>`美食` `评价` `写作` |
| [学术写作助手](https://lobechat.com/discover/assistant/academic-writing-assistant)<br/><sup>By **[swarfte](https://github.com/swarfte)** on **2025-06-17**</sup> | 专业的学术研究论文写作和正式文档编写专家<br/>`学术写作` `研究` `正式风格` |
| [美食评论员🍟](https://lobechat.com/discover/assistant/food-reviewer)<br/><sup>By **[renhai-lab](https://github.com/renhai-lab)** on **2025-06-17**</sup> | 美食评价专家<br/>`美食` `评价` `写作` |
| [Minecraft 资深开发者](https://lobechat.com/discover/assistant/java-development)<br/><sup>By **[iamyuuk](https://github.com/iamyuuk)** on **2025-06-17**</sup> | 擅长高级 Java 开发及 Minecraft 开发<br/>`开发` `编程` `minecraft` `java` |
> 📊 Total agents: [<kbd>**505**</kbd> ](https://lobechat.com/discover/assistants)
@@ -667,7 +667,7 @@ API Key 是使用 LobeChat 进行大语言模型会话的必要信息,本节
## 🧩 插件体系
插件提供了扩展 LobeChat [Function Calling][docs-functionc-call] 能力的方法。可以用于引入新的 Function Calling,甚至是新的消息结果渲染方式。如果你对插件开发感兴趣,请在 Wiki 中查阅我们的 [📘 插件开发指引][docs-plugin-dev] 。
插件提供了扩展 LobeChat [Function Calling][docs-function-call] 能力的方法。可以用于引入新的 Function Calling,甚至是新的消息结果渲染方式。如果你对插件开发感兴趣,请在 Wiki 中查阅我们的 [📘 插件开发指引][docs-plugin-dev] 。
- [lobe-chat-plugins][lobe-chat-plugins]:插件索引从该仓库的 index.json 中获取插件列表并显示给用户。
- [chat-plugin-template][chat-plugin-template]:插件开发模版,你可以通过项目模版快速新建插件项目。
@@ -839,7 +839,7 @@ This project is [LobeHub Community License](./LICENSE) licensed.
[docker-size-link]: https://hub.docker.com/r/lobehub/lobe-chat-database
[docker-size-shield]: https://img.shields.io/docker/image-size/lobehub/lobe-chat-database?color=369eff&labelColor=black&style=flat-square&sort=semver
[docs]: https://lobehub.com/zh/docs/usage/start
[docs-dev-guide]: https://github.com/lobehub/lobe-chat/wiki/index
[docs-dev-guide]: https://lobehub.com/docs/development/start
[docs-docker]: https://lobehub.com/zh/docs/self-hosting/server-database/docker-compose
[docs-env-var]: https://lobehub.com/docs/self-hosting/environment-variables
[docs-feat-agent]: https://lobehub.com/docs/usage/features/agent-market
@@ -858,8 +858,8 @@ This project is [LobeHub Community License](./LICENSE) licensed.
[docs-feat-theme]: https://lobehub.com/docs/usage/features/theme
[docs-feat-tts]: https://lobehub.com/docs/usage/features/tts
[docs-feat-vision]: https://lobehub.com/docs/usage/features/vision
[docs-functionc-call]: https://lobehub.com/zh/blog/openai-function-call
[docs-lighthouse]: https://github.com/lobehub/lobe-chat/wiki/Lighthouse.zh-CN
[docs-function-call]: https://lobehub.com/zh/blog/openai-function-call
[docs-lighthouse]: https://lobehub.com/docs/development/others/lighthouse
[docs-plugin-dev]: https://lobehub.com/docs/usage/plugins/development
[docs-self-hosting]: https://lobehub.com/docs/self-hosting/start
[docs-upstream-sync]: https://lobehub.com/docs/self-hosting/advanced/upstream-sync
+1 -1
View File
@@ -8,7 +8,7 @@ module.exports = defineConfig({
'ar',
'bg-BG',
'zh-TW',
'en-US',
'en',
'ru-RU',
'ja-JP',
'ko-KR',
+16
View File
@@ -4,3 +4,19 @@ ignore-workspace-root-check=true
electron_mirror=https://npmmirror.com/mirrors/electron/
electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/
public-hoist-pattern[]=*@umijs/lint*
public-hoist-pattern[]=*unicorn*
public-hoist-pattern[]=*changelog*
public-hoist-pattern[]=*commitlint*
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*postcss*
public-hoist-pattern[]=*prettier*
public-hoist-pattern[]=*remark*
public-hoist-pattern[]=*semantic-release*
public-hoist-pattern[]=*stylelint*
public-hoist-pattern[]=@auth/core
public-hoist-pattern[]=@clerk/backend
public-hoist-pattern[]=@clerk/types
public-hoist-pattern[]=pdfjs-dist
+62
View File
@@ -0,0 +1,62 @@
# Prettierignore for LobeHub
################################################################
# general
.DS_Store
.editorconfig
.idea
.history
.temp
.env.local
.husky
.npmrc
.gitkeep
venv
temp
tmp
LICENSE
# dependencies
node_modules
*.log
*.lock
package-lock.json
# ci
coverage
.coverage
.eslintcache
.stylelintcache
test-output
__snapshots__
*.snap
# production
dist
es
lib
logs
# umi
.umi
.umi-production
.umi-test
.dumi/tmp*
# ignore files
.*ignore
# docker
docker
Dockerfile*
# image
*.webp
*.gif
*.png
*.jpg
*.svg
# misc
# add other ignore file below
.next
+1
View File
@@ -0,0 +1 @@
module.exports = require('@lobehub/lint').prettier;
+1
View File
@@ -0,0 +1 @@
module.exports = require('@lobehub/lint').remarklint;
+39
View File
@@ -0,0 +1,39 @@
# Stylelintignore for LobeHub
################################################################
# dependencies
node_modules
# ci
coverage
.coverage
# production
dist
es
lib
logs
# framework specific
.next
.umi
.umi-production
.umi-test
.dumi/tmp*
# temporary directories
tmp
temp
.temp
.local
docs/.local
# cache directories
.cache
# AI coding tools directories
.claude
.serena
# MCP tools
/.serena/**
+9
View File
@@ -0,0 +1,9 @@
const config = require('@lobehub/lint').stylelint;
module.exports = {
...config,
rules: {
'selector-id-pattern': null,
...config.rules,
},
};
+38 -42
View File
@@ -156,24 +156,26 @@ apps/desktop/src/main/
- 事件广播:向渲染进程通知授权状态变化
```typescript
// 认证流程示例
@ipcClientEvent('requestAuthorization')
async requestAuthorization(config: DataSyncConfig) {
// 生成状态参数防止 CSRF 攻击
this.authRequestState = crypto.randomBytes(16).toString('hex');
import { ControllerModule, IpcMethod } from '@/controllers';
// 构建授权 URL
const authUrl = new URL('/oidc/auth', remoteUrl);
authUrl.search = querystring.stringify({
client_id: 'lobe-chat',
response_type: 'code',
redirect_uri: `${protocolPrefix}://auth/callback`,
scope: 'openid profile',
state: this.authRequestState,
});
export default class AuthCtr extends ControllerModule {
static override groupName = 'auth';
// 在默认浏览器中打开授权 URL
await shell.openExternal(authUrl.toString());
@IpcMethod()
async requestAuthorization(config: DataSyncConfig) {
this.authRequestState = crypto.randomBytes(16).toString('hex');
const authUrl = new URL('/oidc/auth', remoteUrl);
authUrl.search = querystring.stringify({
client_id: 'lobe-chat',
redirect_uri: `${protocolPrefix}://auth/callback`,
response_type: 'code',
scope: 'openid profile',
state: this.authRequestState,
});
await shell.openExternal(authUrl.toString());
}
}
```
@@ -267,20 +269,27 @@ export class ShortcutManager {
- 注入 App 实例
```typescript
// 控制器基类和装饰器
import { ControllerModule, IpcMethod, IpcServerMethod } from '@/controllers'
export class ControllerModule implements IControllerModule {
constructor(public app: App) {
this.app = app;
this.app = app
}
}
// IPC 客户端事件装饰器
export const ipcClientEvent = (method: keyof ClientDispatchEvents) =>
ipcDecorator(method, 'client');
export class BrowserWindowsCtr extends ControllerModule {
static override readonly groupName = 'windows' // must be readonly
// IPC 服务器事件装饰器
export const ipcServerEvent = (method: keyof ServerDispatchEvents) =>
ipcDecorator(method, 'server');
@IpcMethod()
openSettingsWindow(params?: OpenSettingsWindowOptions) {
// ...
}
@IpcServerMethod()
handleServerCommand(payload: any) {
// ...
}
}
```
2. **IoC 容器**
@@ -346,26 +355,13 @@ makeSureDirExist(storagePath);
- 自动映射控制器方法到 IPC 事件
```typescript
// IPC 事件初始化
private initializeIPCEvents() {
// 注册客户端事件处理程序
this.ipcClientEventMap.forEach((eventInfo, key) => {
ipcMain.handle(key, async (e, ...data) => {
return await eventInfo.controller[eventInfo.methodName](...data);
});
});
import { ensureElectronIpc } from '@/utils/electron/ipc';
// 注册服务器事件处理程序
const ipcServerEvents = {} as ElectronIPCEventHandler;
this.ipcServerEventMap.forEach((eventInfo, key) => {
ipcServerEvents[key] = async (payload) => {
return await eventInfo.controller[eventInfo.methodName](payload);
};
});
// 渲染进程中使用 type-safe proxy 调用主进程方法
const ipc = ensureElectronIpc();
// 创建 IPC 服务器
this.ipcServer = new ElectronIPCServer(name, ipcServerEvents);
}
await ipc.localSystem.readLocalFile({ path });
await ipc.system.updateLocale('en-US');
```
2. **事件广播**
+42 -6
View File
@@ -32,7 +32,7 @@ pnpm install-isolated
pnpm electron:dev
# Type checking
pnpm typecheck
pnpm type-check
# Run tests
pnpm test
@@ -66,9 +66,9 @@ cp .env.desktop .env
pnpm electron:dev # Start with hot reload
# 2. Code Quality
pnpm lint # ESLint checking
pnpm format # Prettier formatting
pnpm typecheck # TypeScript validation
pnpm lint # ESLint checking
pnpm format # Prettier formatting
pnpm type-check # TypeScript validation
# 3. Testing
pnpm test # Run Vitest tests
@@ -183,10 +183,18 @@ The `App.ts` class orchestrates the entire application lifecycle through key pha
#### 🔌 Dependency Injection & Event System
- **IoC Container** - WeakMap-based container for decorated controller methods
- **Decorator Registration** - `@ipcClientEvent` and `@ipcServerEvent` decorators
- **Typed IPC Decorators** - `@IpcMethod` and `@IpcServerMethod` wire controller methods into type-safe channels
- **Automatic Event Mapping** - Events registered during controller loading
- **Service Locator** - Type-safe service and controller retrieval
##### 🧠 Type-Safe IPC Flow
- **Async Context Propagation** - `src/main/utils/ipc/base.ts` captures the `IpcContext` with `AsyncLocalStorage`, so controller logic can call `getIpcContext()` anywhere inside an IPC handler without explicitly threading arguments.
- **Service Constructors Registry** - `src/main/controllers/registry.ts` exports `controllerIpcConstructors`, `DesktopIpcServices`, and `DesktopServerIpcServices`, enabling automatic typing of both renderer and server IPC proxies.
- **Renderer Proxy Helper** - `src/utils/electron/ipc.ts` exposes `ensureElectronIpc()` which lazily builds a proxy on top of `window.electronAPI.invoke`, giving React/Next.js code a type-safe API surface without exposing raw proxies in preload.
- **Server Proxy Helper** - `src/server/modules/ElectronIPCClient/index.ts` mirrors the same typing strategy for the Next.js server runtime, providing a dedicated proxy for `@IpcServerMethod` handlers.
- **Shared Typings Package** - `apps/desktop/src/main/exports.d.ts` augments `@lobechat/electron-client-ipc` so every package can consume `DesktopIpcServices` without importing desktop business code directly.
#### 🪟 Window Management
- **Theme-Aware Windows** - Automatic adaptation to system dark/light mode
@@ -235,6 +243,7 @@ The `App.ts` class orchestrates the entire application lifecycle through key pha
#### 🎮 Controller Pattern
- **Typed IPC Decorators** - Controllers extend `ControllerModule` and expose renderer methods via `@IpcMethod`
- **IPC Event Handling** - Processes events from renderer with decorator-based registration
- **Lifecycle Hooks** - `beforeAppReady` and `afterAppReady` for initialization phases
- **Type-Safe Communication** - Strong typing for all IPC events and responses
@@ -256,6 +265,33 @@ The `App.ts` class orchestrates the entire application lifecycle through key pha
- **Context Awareness** - Events include sender context for window-specific operations
- **Error Propagation** - Centralized error handling with proper status codes
##### 🧩 Renderer IPC Helper
Renderer code uses a lightweight proxy generated at runtime to keep IPC calls type-safe without exposing raw Electron objects through `contextBridge`. Use the helper exported from `src/utils/electron/ipc.ts` to access the main-process services:
```ts
import { ensureElectronIpc } from '@/utils/electron/ipc';
const ipc = ensureElectronIpc();
await ipc.windows.openSettingsWindow({ tab: 'provider' });
```
The helper internally builds a proxy on top of `window.electronAPI.invoke`, so no proxy objects need to be cloned across the preload boundary.
##### 🖥️ Server IPC Helper
Next.js (Node) modules use the same proxy pattern via `ensureElectronServerIpc` from `src/server/modules/ElectronIPCClient`. It lazily wraps the socket-based `ElectronIpcClient` so server code can call controllers with full type safety:
```ts
import { ensureElectronServerIpc } from '@/server/modules/ElectronIPCClient';
const ipc = ensureElectronServerIpc();
const dbPath = await ipc.system.getDatabasePath();
await ipc.upload.deleteFiles(['foo.txt']);
```
All server methods are declared via `@IpcServerMethod` and live in dedicated controller classes, keeping renderer typings clean.
#### 🛡️ Security Features
- **OAuth 2.0 + PKCE** - Secure authentication with state parameter validation
@@ -277,7 +313,7 @@ tests/ # Integration tests
```bash
pnpm test # Run all tests
pnpm test:watch # Watch mode
pnpm typecheck # Type validation
pnpm type-check # Type validation
```
### Test Coverage
+31 -6
View File
@@ -32,7 +32,7 @@ pnpm install-isolated
pnpm electron:dev
# 类型检查
pnpm typecheck
pnpm type-check
# 运行测试
pnpm test
@@ -66,9 +66,9 @@ cp .env.desktop .env
pnpm electron:dev # 启动热重载开发服务器
# 2. 代码质量
pnpm lint # ESLint 检查
pnpm format # Prettier 格式化
pnpm typecheck # TypeScript 验证
pnpm lint # ESLint 检查
pnpm format # Prettier 格式化
pnpm type-check # TypeScript 验证
# 3. 测试
pnpm test # 运行 Vitest 测试
@@ -183,7 +183,7 @@ src/main/core/
#### 🔌 依赖注入和事件系统
- **IoC 容器** - 基于 WeakMap 的装饰控制器方法容器
- **装饰器注册** - `@ipcClientEvent``@ipcServerEvent` 装饰器
- **装饰器注册** - `@IpcMethod``@IpcServerMethod` 装饰器
- **自动事件映射** - 控制器加载期间注册的事件
- **服务定位器** - 类型安全的服务和控制器检索
@@ -256,6 +256,31 @@ src/main/core/
- **上下文感知** - 事件包含用于窗口特定操作的发送者上下文
- **错误传播** - 具有适当状态码的集中错误处理
##### 🧩 渲染器 IPC 助手
渲染端通过 `src/utils/electron/ipc.ts` 提供的 `ensureElectronIpc` 获得一个运行时代理,无需在 preload 中暴露 Proxy 对象即可获得类型安全的调用体验:
```ts
import { ensureElectronIpc } from '@/utils/electron/ipc';
const ipc = ensureElectronIpc();
await ipc.windows.openSettingsWindow({ tab: 'provider' });
```
##### 🖥️ Server IPC 助手
Next.js 服务端模块可通过 `ensureElectronServerIpc`(位于 `src/server/modules/ElectronIPCClient`)获得同样的类型安全代理,并复用 socket IPC 通道:
```ts
import { ensureElectronServerIpc } from '@/server/modules/ElectronIPCClient';
const ipc = ensureElectronServerIpc();
const path = await ipc.system.getDatabasePath();
await ipc.upload.deleteFiles(['foo.txt']);
```
所有 `@IpcServerMethod` 方法都放在独立的控制器中,这样渲染端的类型推导不会包含这些仅供服务器调用的通道。
#### 🛡️ 安全功能
- **OAuth 2.0 + PKCE** - 具有状态参数验证的安全认证
@@ -277,7 +302,7 @@ tests/ # 集成测试
```bash
pnpm test # 运行所有测试
pnpm test:watch # 监视模式
pnpm typecheck # 类型验证
pnpm type-check # 类型验证
```
### 测试覆盖
+37 -1
View File
@@ -17,6 +17,10 @@ console.log(`🏗️ Building for architecture: ${arch}`);
const isNightly = channel === 'nightly';
const isBeta = packageJSON.name.includes('beta');
// Keep only these Electron Framework localization folders (*.lproj)
// (aligned with previous Electron Forge build config)
const keepLanguages = new Set(['en', 'en_GB', 'en-US', 'en_US']);
// https://www.electron.build/code-signing-mac#how-to-disable-code-signing-during-the-build-process-on-macos
if (!hasAppleCertificate) {
// Disable auto discovery to keep electron-builder from searching unavailable signing identities
@@ -54,7 +58,7 @@ const config = {
*/
afterPack: async (context) => {
// Only process macOS builds
if (context.electronPlatformName !== 'darwin') {
if (!['darwin', 'mas'].includes(context.electronPlatformName)) {
return;
}
@@ -68,6 +72,36 @@ const config = {
);
const assetsCarDest = path.join(resourcesPath, 'Assets.car');
// Remove unused Electron Framework localizations to reduce app size
// Equivalent to:
// ../../Frameworks/Electron Framework.framework/Versions/A/Resources/*.lproj
const frameworkResourcePath = path.join(
context.appOutDir,
`${context.packager.appInfo.productFilename}.app`,
'Contents',
'Frameworks',
'Electron Framework.framework',
'Versions',
'A',
'Resources',
);
try {
const entries = await fs.readdir(frameworkResourcePath);
await Promise.all(
entries.map(async (file) => {
if (!file.endsWith('.lproj')) return;
const lang = file.split('.')[0];
if (keepLanguages.has(lang)) return;
await fs.rm(path.join(frameworkResourcePath, file), { force: true, recursive: true });
}),
);
} catch {
// Non-critical: folder may not exist depending on packaging details
}
try {
await fs.access(assetsCarSource);
await fs.copyFile(assetsCarSource, assetsCarDest);
@@ -106,6 +140,8 @@ const config = {
files: [
'dist',
'resources',
// Ensure Next export assets are packaged
'dist/next/**/*',
'!resources/locales',
'!dist/next/docs',
'!dist/next/packages',
+1
View File
@@ -39,6 +39,7 @@ export default defineConfig({
resolve: {
alias: {
'~common': resolve(__dirname, 'src/common'),
'@': resolve(__dirname, 'src/main'),
},
},
},
+29 -12
View File
@@ -11,21 +11,30 @@
"author": "LobeHub",
"main": "./dist/main/index.js",
"scripts": {
"build": "npm run typecheck && electron-vite build",
"build": "electron-vite build",
"build-local": "npm run build && electron-builder --dir --config electron-builder.js --c.mac.notarize=false -c.mac.identity=null --c.asar=false",
"build:linux": "npm run build && electron-builder --linux --config electron-builder.js --publish never",
"build:mac": "npm run build && electron-builder --mac --config electron-builder.js --publish never",
"build:mac:local": "npm run build && UPDATE_CHANNEL=nightly electron-builder --mac --config electron-builder.js --publish never",
"build:win": "npm run build && electron-builder --win --config electron-builder.js --publish never",
"dev": "electron-vite dev",
"electron:dev": "electron-vite dev",
"electron:run-unpack": "electron .",
"format": "prettier --write ",
"i18n": "tsx scripts/i18nWorkflow/index.ts && lobe-i18n",
"postinstall": "electron-builder install-app-deps",
"install-isolated": "pnpm install",
"lint": "eslint --cache ",
"lint": "npm run lint:ts && npm run lint:style && npm run type-check && npm run lint:circular",
"lint:circular": "npm run lint:circular:main && npm run lint:circular:packages",
"lint:circular:main": "dpdm src/**/*.ts --no-warning --no-tree --exit-code circular:1 --no-progress -T true --skip-dynamic-imports circular",
"lint:circular:packages": "dpdm packages/**/src/**/*.ts --no-warning --no-tree --exit-code circular:1 --no-progress -T true --skip-dynamic-imports circular",
"lint:md": "remark . --silent --output",
"lint:style": "stylelint \"{src,tests}/**/*.{js,jsx,ts,tsx}\" --fix",
"lint:ts": "eslint \"{src,tests}/**/*.{js,jsx,ts,tsx}\" --fix",
"start": "electron-vite preview",
"stylelint": "stylelint \"src/**/*.{js,jsx,ts,tsx}\" --fix",
"test": "vitest --run",
"type-check": "tsgo --noEmit -p tsconfig.json",
"typecheck": "tsgo --noEmit -p tsconfig.json"
},
"dependencies": {
@@ -33,7 +42,8 @@
"electron-window-state": "^5.0.3",
"fetch-socks": "^1.3.2",
"get-port-please": "^3.2.0",
"pdfjs-dist": "4.10.38"
"pdfjs-dist": "4.10.38",
"superjson": "^2.2.6"
},
"devDependencies": {
"@electron-toolkit/eslint-config-prettier": "^3.0.0",
@@ -41,45 +51,52 @@
"@electron-toolkit/preload": "^3.0.2",
"@electron-toolkit/tsconfig": "^2.0.0",
"@electron-toolkit/utils": "^4.0.0",
"@lobechat/desktop-bridge": "workspace:*",
"@lobechat/electron-client-ipc": "workspace:*",
"@lobechat/electron-server-ipc": "workspace:*",
"@lobechat/file-loaders": "workspace:*",
"@lobehub/i18n-cli": "^1.25.1",
"@modelcontextprotocol/sdk": "^1.24.3",
"@types/async-retry": "^1.4.9",
"@types/lodash": "^4.17.21",
"@types/resolve": "^1.20.6",
"@types/semver": "^7.7.1",
"@types/set-cookie-parser": "^2.4.10",
"@typescript/native-preview": "7.0.0-dev.20250711.1",
"@t3-oss/env-core": "^0.13.8",
"@typescript/native-preview": "7.0.0-dev.20251210.1",
"async-retry": "^1.3.3",
"consola": "^3.4.2",
"cookie": "^1.1.1",
"diff": "^8.0.2",
"electron": "^38.7.2",
"electron-builder": "^26.0.12",
"electron-devtools-installer": "^3.2.0",
"electron-is": "^3.0.0",
"electron-log": "^5.4.3",
"electron-store": "^8.2.0",
"electron-vite": "^4.0.1",
"es-toolkit": "^1.43.0",
"eslint": "^8.57.1",
"execa": "^9.6.1",
"fast-glob": "^3.3.3",
"fix-path": "^5.0.0",
"happy-dom": "^20.0.11",
"http-proxy-agent": "^7.0.2",
"https-proxy-agent": "^7.0.6",
"i18next": "^25.6.3",
"i18next": "^25.7.2",
"just-diff": "^6.0.2",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"prettier": "^3.7.4",
"remark-cli": "^12.0.1",
"resolve": "^1.22.11",
"semver": "^7.7.3",
"set-cookie-parser": "^2.7.2",
"tsx": "^4.20.6",
"stylelint": "^15.11.0",
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"undici": "^7.16.0",
"uuid": "^13.0.0",
"vite": "^7.2.4",
"vitest": "^3.2.4"
"vite": "^7.2.7",
"vitest": "^3.2.4",
"zod": "^3.25.76"
},
"pnpm": {
"onlyBuiltDependencies": [
@@ -87,4 +104,4 @@
"electron-builder"
]
}
}
}
+1
View File
@@ -2,4 +2,5 @@ packages:
- '../../packages/electron-server-ipc'
- '../../packages/electron-client-ipc'
- '../../packages/file-loaders'
- '../../packages/desktop-bridge'
- '.'
+25 -31
View File
@@ -1,32 +1,26 @@
{
"actions": {
"add": "إضافة",
"back": "عودة",
"cancel": لغاء",
"close": "إغلاق",
"confirm": "تأكيد",
"delete": "حذف",
"edit": "تعديل",
"more": "المزيد",
"next": "التالي",
"ok": "حسناً",
"previous": "السابق",
"refresh": "تحديث",
"remove": "إزالة",
"retry": "إعادة المحاولة",
"save": "حفظ",
"search": "بحث",
"submit": "إرسال"
},
"app": {
"description": "منصة تعاون مساعدك الذكي",
"name": "LobeHub"
},
"status": {
"error": "خطأ",
"info": "معلومات",
"loading": "جارٍ التحميل",
"success": "نجاح",
"warning": "تحذير"
}
}
"actions.add": "إضافة",
"actions.back": "عودة",
"actions.cancel": "إلغاء",
"actions.close": غلاق",
"actions.confirm": "تأكيد",
"actions.delete": "حذف",
"actions.edit": "تعديل",
"actions.more": "المزيد",
"actions.next": "التالي",
"actions.ok": "حسناً",
"actions.previous": "السابق",
"actions.refresh": "تحديث",
"actions.remove": "إزالة",
"actions.retry": "إعادة المحاولة",
"actions.save": "حفظ",
"actions.search": "بحث",
"actions.submit": "إرسال",
"app.description": "منصة تعاون مساعدك الذكي",
"app.name": "LobeHub",
"status.error": "خطأ",
"status.info": "معلومات",
"status.loading": "جارٍ التحميل",
"status.success": "نجاح",
"status.warning": "تحذير"
}
+22 -30
View File
@@ -1,31 +1,23 @@
{
"about": {
"button": "تأكيد",
"detail": "تطبيق دردشة يعتمد على نموذج لغة كبير",
"message": "{{appName}} {{appVersion}}",
"title": "حول"
},
"confirm": {
"cancel": "إلغاء",
"no": "لا",
"title": "تأكيد",
"yes": "نعم"
},
"error": {
"button": "تأكيد",
"detail": "حدث خطأ أثناء العملية، يرجى المحاولة لاحقًا",
"message": "حدث خطأ",
"title": "خطأ"
},
"update": {
"downloadAndInstall": "تنزيل وتثبيت",
"downloadComplete": "اكتمل التنزيل",
"downloadCompleteMessage": "تم تنزيل حزمة التحديث، هل ترغب في التثبيت الآن؟",
"installLater": "تثبيت لاحقًا",
"installNow": "تثبيت الآن",
"later": "تذكير لاحقًا",
"newVersion": "تم اكتشاف إصدار جديد",
"newVersionAvailable": "تم اكتشاف إصدار جديد: {{version}}",
"skipThisVersion": "تخطي هذا الإصدار"
}
}
"about.button": "تأكيد",
"about.detail": "تطبيق دردشة يعتمد على نموذج لغة كبير",
"about.message": "{{appName}} {{appVersion}}",
"about.title": "حول",
"confirm.cancel": "إلغاء",
"confirm.no": "لا",
"confirm.title": "تأكيد",
"confirm.yes": "نعم",
"error.button": "تأكيد",
"error.detail": "حدث خطأ أثناء العملية، يرجى المحاولة لاحقًا",
"error.message": "حدث خطأ",
"error.title": "خطأ",
"update.downloadAndInstall": "تنزيل وتثبيت",
"update.downloadComplete": "اكتمل التنزيل",
"update.downloadCompleteMessage": "تم تنزيل حزمة التحديث، هل ترغب في التثبيت الآن؟",
"update.installLater": "تثبيت لاحقًا",
"update.installNow": "تثبيت الآن",
"update.later": "تذكير لاحقًا",
"update.newVersion": "تم اكتشاف إصدار جديد",
"update.newVersionAvailable": "تم اكتشاف إصدار جديد: {{version}}",
"update.skipThisVersion": "تخطي هذا الإصدار"
}
+52 -70
View File
@@ -1,71 +1,53 @@
{
"common": {
"checkUpdates": "التحقق من التحديثات..."
},
"dev": {
"devPanel": "لوحة المطور",
"devTools": "أدوات المطور",
"forceReload": "إعادة تحميل قسري",
"openStore": "فتح ملف التخزين",
"refreshMenu": "تحديث القائمة",
"reload": "إعادة تحميل",
"title": "تطوير"
},
"edit": {
"copy": "نسخ",
"cut": "قص",
"delete": "حذف",
"paste": "لصق",
"redo": "إعادة",
"selectAll": "تحديد الكل",
"speech": "صوت",
"startSpeaking": "بدء القراءة",
"stopSpeaking": "إيقاف القراءة",
"title": "تحرير",
"undo": "تراجع"
},
"file": {
"preferences": "التفضيلات",
"quit": "خروج",
"title": "ملف"
},
"help": {
"about": "حول",
"githubRepo": "مستودع GitHub",
"reportIssue": "الإبلاغ عن مشكلة",
"title": "مساعدة",
"visitWebsite": "زيارة الموقع الرسمي"
},
"macOS": {
"about": "حول {{appName}}",
"devTools": "أدوات مطور LobeHub",
"hide": "إخفاء {{appName}}",
"hideOthers": "إخفاء الآخرين",
"preferences": "إعدادات مفضلة...",
"services": "خدمات",
"unhide": ظهار الكل"
},
"tray": {
"open": "فتح {{appName}}",
"quit": "خروج",
"show": "عرض {{appName}}"
},
"view": {
"forceReload": "إعادة تحميل قسري",
"reload": "إعادة تحميل",
"resetZoom": "إعادة تعيين التكبير",
"title": "عرض",
"toggleFullscreen": "تبديل وضع ملء الشاشة",
"zoomIn": "تكبير",
"zoomOut": "تصغير"
},
"window": {
"bringAllToFront": "إحضار جميع النوافذ إلى الأمام",
"close": "إغلاق",
"front": "إحضار جميع النوافذ إلى الأمام",
"minimize": "تصغير",
"title": "نافذة",
"toggleFullscreen": "تبديل وضع ملء الشاشة",
"zoom": "تكبير"
}
}
"common.checkUpdates": "التحقق من التحديثات...",
"dev.devPanel": "لوحة المطور",
"dev.devTools": "أدوات المطور",
"dev.forceReload": "إعادة تحميل قسري",
"dev.openStore": "فتح ملف التخزين",
"dev.refreshMenu": "تحديث القائمة",
"dev.reload": "إعادة تحميل",
"dev.title": "تطوير",
"edit.copy": "نسخ",
"edit.cut": "قص",
"edit.delete": "حذف",
"edit.paste": "لصق",
"edit.redo": "إعادة",
"edit.selectAll": "تحديد الكل",
"edit.speech": وت",
"edit.startSpeaking": "بدء القراءة",
"edit.stopSpeaking": "إيقاف القراءة",
"edit.title": "تحرير",
"edit.undo": "تراجع",
"file.preferences": "التفضيلات",
"file.quit": "خروج",
"file.title": "ملف",
"help.about": "حول",
"help.githubRepo": "مستودع GitHub",
"help.reportIssue": "الإبلاغ عن مشكلة",
"help.title": "مساعدة",
"help.visitWebsite": "زيارة الموقع الرسمي",
"macOS.about": "حول {{appName}}",
"macOS.devTools": "أدوات مطور LobeHub",
"macOS.hide": "إخفاء {{appName}}",
"macOS.hideOthers": "إخفاء الآخرين",
"macOS.preferences": "إعدادات مفضلة...",
"macOS.services": "خدمات",
"macOS.unhide": "إظهار الكل",
"tray.open": "فتح {{appName}}",
"tray.quit": "خروج",
"tray.show": "عرض {{appName}}",
"view.forceReload": "إعادة تحميل قسري",
"view.reload": "إعادة تحميل",
"view.resetZoom": "إعادة تعيين التكبير",
"view.title": "عرض",
"view.toggleFullscreen": "تبديل وضع ملء الشاشة",
"view.zoomIn": "تكبير",
"view.zoomOut": "تصغير",
"window.bringAllToFront": حضار جميع النوافذ إلى الأمام",
"window.close": "إغلاق",
"window.front": "إحضار جميع النوافذ إلى الأمام",
"window.minimize": "تصغير",
"window.title": "نافذة",
"window.toggleFullscreen": "تبديل وضع ملء الشاشة",
"window.zoom": "تكبير"
}
@@ -1,32 +1,26 @@
{
"actions": {
"add": "Добави",
"back": "Назад",
"cancel": "Отмени",
"close": "Затвори",
"confirm": "Потвърди",
"delete": "Изтрий",
"edit": "Редактирай",
"more": "Повече",
"next": "Следващ",
"ok": "Добре",
"previous": "Предишен",
"refresh": "Освежи",
"remove": "Премахни",
"retry": "Опитай отново",
"save": "Запази",
"search": "Търси",
"submit": "Изпрати"
},
"app": {
"description": "Твоята платформа за сътрудничество с AI асистент",
"name": "LobeHub"
},
"status": {
"error": "Грешка",
"info": "Информация",
"loading": "Зареждане",
"success": "Успех",
"warning": "Предупреждение"
}
}
"actions.add": "Добави",
"actions.back": "Назад",
"actions.cancel": "Отмени",
"actions.close": "Затвори",
"actions.confirm": "Потвърди",
"actions.delete": "Изтрий",
"actions.edit": "Редактирай",
"actions.more": "Повече",
"actions.next": "Следващ",
"actions.ok": "Добре",
"actions.previous": "Предишен",
"actions.refresh": "Освежи",
"actions.remove": "Премахни",
"actions.retry": "Опитай отново",
"actions.save": "Запази",
"actions.search": "Търси",
"actions.submit": "Изпрати",
"app.description": "Твоята платформа за сътрудничество с AI асистент",
"app.name": "LobeHub",
"status.error": "Грешка",
"status.info": "Информация",
"status.loading": "Зареждане",
"status.success": "Успех",
"status.warning": "Предупреждение"
}
@@ -1,31 +1,23 @@
{
"about": {
"button": "Потвърди",
"detail": "Приложение за чат, базирано на голям езиков модел",
"message": "{{appName}} {{appVersion}}",
"title": "За нас"
},
"confirm": {
"cancel": "Отказ",
"no": "Не",
"title": "Потвърждение",
"yes": "Да"
},
"error": {
"button": "Потвърди",
"detail": "Възникна грешка по време на операцията, моля опитайте отново по-късно",
"message": "Възникна грешка",
"title": "Грешка"
},
"update": {
"downloadAndInstall": "Изтегли и инсталирай",
"downloadComplete": "Изтеглянето е завършено",
"downloadCompleteMessage": "Актуализационният пакет е изтеглен, желаете ли да го инсталирате веднага?",
"installLater": "Инсталирай по-късно",
"installNow": "Инсталирай сега",
"later": "Напомни по-късно",
"newVersion": "Открита нова версия",
"newVersionAvailable": "Открита нова версия: {{version}}",
"skipThisVersion": "Пропусни тази версия"
}
}
"about.button": "Потвърди",
"about.detail": "Приложение за чат, базирано на голям езиков модел",
"about.message": "{{appName}} {{appVersion}}",
"about.title": "За нас",
"confirm.cancel": "Отказ",
"confirm.no": "Не",
"confirm.title": "Потвърждение",
"confirm.yes": "Да",
"error.button": "Потвърди",
"error.detail": "Възникна грешка по време на операцията, моля опитайте отново по-късно",
"error.message": "Възникна грешка",
"error.title": "Грешка",
"update.downloadAndInstall": "Изтегли и инсталирай",
"update.downloadComplete": "Изтеглянето е завършено",
"update.downloadCompleteMessage": "Актуализационният пакет е изтеглен, желаете ли да го инсталирате веднага?",
"update.installLater": "Инсталирай по-късно",
"update.installNow": "Инсталирай сега",
"update.later": "Напомни по-късно",
"update.newVersion": "Открита нова версия",
"update.newVersionAvailable": "Открита нова версия: {{version}}",
"update.skipThisVersion": "Пропусни тази версия"
}
+52 -70
View File
@@ -1,71 +1,53 @@
{
"common": {
"checkUpdates": "Проверка за актуализации..."
},
"dev": {
"devPanel": "Панел на разработчика",
"devTools": "Инструменти за разработчици",
"forceReload": "Принудително презареждане",
"openStore": "Отворете файла за съхранение",
"refreshMenu": "Освежаване на менюто",
"reload": "Презареждане",
"title": "Разработка"
},
"edit": {
"copy": "Копиране",
"cut": "Изрязване",
"delete": "Изтрий",
"paste": "Поставяне",
"redo": "Повторно",
"selectAll": "Избери всичко",
"speech": "Глас",
"startSpeaking": "Започни четене",
"stopSpeaking": "Спри четенето",
"title": "Редактиране",
"undo": "Отмяна"
},
"file": {
"preferences": "Предпочитания",
"quit": "Изход",
"title": "Файл"
},
"help": {
"about": "За",
"githubRepo": "GitHub хранилище",
"reportIssue": "Докладвай проблем",
"title": "Помощ",
"visitWebsite": "Посети уебсайта"
},
"macOS": {
"about": "За {{appName}}",
"devTools": "Инструменти за разработчици на LobeHub",
"hide": "Скрий {{appName}}",
"hideOthers": "Скрий другите",
"preferences": "Настройки...",
"services": "Услуги",
"unhide": окажи всичко"
},
"tray": {
"open": "Отвори {{appName}}",
"quit": "Изход",
"show": "Покажи {{appName}}"
},
"view": {
"forceReload": "Принудително презареждане",
"reload": "Презареждане",
"resetZoom": "Нулиране на мащаба",
"title": "Изглед",
"toggleFullscreen": "Превключи на цял екран",
"zoomIn": "Увеличи",
"zoomOut": "Намали"
},
"window": {
"bringAllToFront": "Премести всички прозорци напред",
"close": "Затвори",
"front": "Премести всички прозорци напред",
"minimize": "Минимизирай",
"title": "Прозорец",
"toggleFullscreen": "Превключи на цял екран",
"zoom": "Мащаб"
}
}
"common.checkUpdates": "Проверка за актуализации...",
"dev.devPanel": "Панел на разработчика",
"dev.devTools": "Инструменти за разработчици",
"dev.forceReload": "Принудително презареждане",
"dev.openStore": "Отворете файла за съхранение",
"dev.refreshMenu": "Освежаване на менюто",
"dev.reload": "Презареждане",
"dev.title": "Разработка",
"edit.copy": "Копиране",
"edit.cut": "Изрязване",
"edit.delete": "Изтрий",
"edit.paste": "Поставяне",
"edit.redo": "Повторно",
"edit.selectAll": "Избери всичко",
"edit.speech": "Глас",
"edit.startSpeaking": "Започни четене",
"edit.stopSpeaking": "Спри четенето",
"edit.title": "Редактиране",
"edit.undo": "Отмяна",
"file.preferences": "Предпочитания",
"file.quit": "Изход",
"file.title": "Файл",
"help.about": "За",
"help.githubRepo": "GitHub хранилище",
"help.reportIssue": "Докладвай проблем",
"help.title": "Помощ",
"help.visitWebsite": "Посети уебсайта",
"macOS.about": "За {{appName}}",
"macOS.devTools": "Инструменти за разработчици на LobeHub",
"macOS.hide": "Скрий {{appName}}",
"macOS.hideOthers": "Скрий другите",
"macOS.preferences": "Настройки...",
"macOS.services": "Услуги",
"macOS.unhide": "Покажи всичко",
"tray.open": "Отвори {{appName}}",
"tray.quit": "Изход",
"tray.show": "Покажи {{appName}}",
"view.forceReload": "Принудително презареждане",
"view.reload": "Презареждане",
"view.resetZoom": "Нулиране на мащаба",
"view.title": "Изглед",
"view.toggleFullscreen": "Превключи на цял екран",
"view.zoomIn": "Увеличи",
"view.zoomOut": "Намали",
"window.bringAllToFront": ремести всички прозорци напред",
"window.close": "Затвори",
"window.front": "Премести всички прозорци напред",
"window.minimize": "Минимизирай",
"window.title": "Прозорец",
"window.toggleFullscreen": "Превключи на цял екран",
"window.zoom": "Мащаб"
}
@@ -1,32 +1,26 @@
{
"actions": {
"add": "Hinzufügen",
"back": "Zurück",
"cancel": "Abbrechen",
"close": "Schließen",
"confirm": "Bestätigen",
"delete": "Löschen",
"edit": "Bearbeiten",
"more": "Mehr",
"next": "Weiter",
"ok": "OK",
"previous": "Zurück",
"refresh": "Aktualisieren",
"remove": "Entfernen",
"retry": "Erneut versuchen",
"save": "Speichern",
"search": "Suchen",
"submit": "Einreichen"
},
"app": {
"description": "Ihre KI-Assistenten-Kollaborationsplattform",
"name": "LobeHub"
},
"status": {
"error": "Fehler",
"info": "Information",
"loading": "Lädt",
"success": "Erfolg",
"warning": "Warnung"
}
}
"actions.add": "Hinzufügen",
"actions.back": "Zurück",
"actions.cancel": "Abbrechen",
"actions.close": "Schließen",
"actions.confirm": "Bestätigen",
"actions.delete": "Löschen",
"actions.edit": "Bearbeiten",
"actions.more": "Mehr",
"actions.next": "Weiter",
"actions.ok": "OK",
"actions.previous": "Zurück",
"actions.refresh": "Aktualisieren",
"actions.remove": "Entfernen",
"actions.retry": "Erneut versuchen",
"actions.save": "Speichern",
"actions.search": "Suchen",
"actions.submit": "Einreichen",
"app.description": "Ihre KI-Assistenten-Kollaborationsplattform",
"app.name": "LobeHub",
"status.error": "Fehler",
"status.info": "Information",
"status.loading": "Lädt",
"status.success": "Erfolg",
"status.warning": "Warnung"
}
@@ -1,31 +1,23 @@
{
"about": {
"button": "Bestätigen",
"detail": "Eine Chat-Anwendung, die auf einem großen Sprachmodell basiert",
"message": "{{appName}} {{appVersion}}",
"title": "Über"
},
"confirm": {
"cancel": "Abbrechen",
"no": "Nein",
"title": "Bestätigung",
"yes": "Ja"
},
"error": {
"button": "Bestätigen",
"detail": "Während der Operation ist ein Fehler aufgetreten, bitte versuchen Sie es später erneut",
"message": "Ein Fehler ist aufgetreten",
"title": "Fehler"
},
"update": {
"downloadAndInstall": "Herunterladen und installieren",
"downloadComplete": "Download abgeschlossen",
"downloadCompleteMessage": "Das Update-Paket wurde heruntergeladen, möchten Sie es jetzt installieren?",
"installLater": "Später installieren",
"installNow": "Jetzt installieren",
"later": "Später erinnern",
"newVersion": "Neue Version gefunden",
"newVersionAvailable": "Neue Version verfügbar: {{version}}",
"skipThisVersion": "Diese Version überspringen"
}
}
"about.button": "Bestätigen",
"about.detail": "Eine Chat-Anwendung, die auf einem großen Sprachmodell basiert",
"about.message": "{{appName}} {{appVersion}}",
"about.title": "Über",
"confirm.cancel": "Abbrechen",
"confirm.no": "Nein",
"confirm.title": "Bestätigung",
"confirm.yes": "Ja",
"error.button": "Bestätigen",
"error.detail": "Während der Operation ist ein Fehler aufgetreten, bitte versuchen Sie es später erneut",
"error.message": "Ein Fehler ist aufgetreten",
"error.title": "Fehler",
"update.downloadAndInstall": "Herunterladen und installieren",
"update.downloadComplete": "Download abgeschlossen",
"update.downloadCompleteMessage": "Das Update-Paket wurde heruntergeladen, möchten Sie es jetzt installieren?",
"update.installLater": "Später installieren",
"update.installNow": "Jetzt installieren",
"update.later": "Später erinnern",
"update.newVersion": "Neue Version gefunden",
"update.newVersionAvailable": "Neue Version verfügbar: {{version}}",
"update.skipThisVersion": "Diese Version überspringen"
}
+52 -70
View File
@@ -1,71 +1,53 @@
{
"common": {
"checkUpdates": "Überprüfen Sie auf Updates..."
},
"dev": {
"devPanel": "Entwicklerpanel",
"devTools": "Entwicklerwerkzeuge",
"forceReload": "Erzwinge Neuladen",
"openStore": "Speicherdatei öffnen",
"refreshMenu": "Menü aktualisieren",
"reload": "Neuladen",
"title": "Entwicklung"
},
"edit": {
"copy": "Kopieren",
"cut": "Ausschneiden",
"delete": "Löschen",
"paste": "Einfügen",
"redo": "Wiederherstellen",
"selectAll": "Alles auswählen",
"speech": "Sprache",
"startSpeaking": "Beginne zu sprechen",
"stopSpeaking": "Stoppe das Sprechen",
"title": "Bearbeiten",
"undo": "Rückgängig"
},
"file": {
"preferences": "Einstellungen",
"quit": "Beenden",
"title": "Datei"
},
"help": {
"about": "Über",
"githubRepo": "GitHub-Repository",
"reportIssue": "Problem melden",
"title": "Hilfe",
"visitWebsite": "Besuche die Website"
},
"macOS": {
"about": "Über {{appName}}",
"devTools": "LobeHub Entwicklerwerkzeuge",
"hide": "{{appName}} ausblenden",
"hideOthers": "Andere ausblenden",
"preferences": "Einstellungen...",
"services": "Dienste",
"unhide": "Alle anzeigen"
},
"tray": {
"open": "{{appName}} öffnen",
"quit": "Beenden",
"show": "{{appName}} anzeigen"
},
"view": {
"forceReload": "Erzwinge Neuladen",
"reload": "Neuladen",
"resetZoom": "Zoom zurücksetzen",
"title": "Ansicht",
"toggleFullscreen": "Vollbild umschalten",
"zoomIn": "Vergrößern",
"zoomOut": "Verkleinern"
},
"window": {
"bringAllToFront": "Alle Fenster in den Vordergrund bringen",
"close": "Schließen",
"front": "Alle Fenster in den Vordergrund bringen",
"minimize": "Minimieren",
"title": "Fenster",
"toggleFullscreen": "Vollbild umschalten",
"zoom": "Zoom"
}
}
"common.checkUpdates": "Überprüfen Sie auf Updates...",
"dev.devPanel": "Entwicklerpanel",
"dev.devTools": "Entwicklerwerkzeuge",
"dev.forceReload": "Erzwinge Neuladen",
"dev.openStore": "Speicherdatei öffnen",
"dev.refreshMenu": "Menü aktualisieren",
"dev.reload": "Neuladen",
"dev.title": "Entwicklung",
"edit.copy": "Kopieren",
"edit.cut": "Ausschneiden",
"edit.delete": "Löschen",
"edit.paste": "Einfügen",
"edit.redo": "Wiederherstellen",
"edit.selectAll": "Alles auswählen",
"edit.speech": "Sprache",
"edit.startSpeaking": "Beginne zu sprechen",
"edit.stopSpeaking": "Stoppe das Sprechen",
"edit.title": "Bearbeiten",
"edit.undo": "Rückgängig",
"file.preferences": "Einstellungen",
"file.quit": "Beenden",
"file.title": "Datei",
"help.about": "Über",
"help.githubRepo": "GitHub-Repository",
"help.reportIssue": "Problem melden",
"help.title": "Hilfe",
"help.visitWebsite": "Besuche die Website",
"macOS.about": "Über {{appName}}",
"macOS.devTools": "LobeHub Entwicklerwerkzeuge",
"macOS.hide": "{{appName}} ausblenden",
"macOS.hideOthers": "Andere ausblenden",
"macOS.preferences": "Einstellungen...",
"macOS.services": "Dienste",
"macOS.unhide": "Alle anzeigen",
"tray.open": "{{appName}} öffnen",
"tray.quit": "Beenden",
"tray.show": "{{appName}} anzeigen",
"view.forceReload": "Erzwinge Neuladen",
"view.reload": "Neuladen",
"view.resetZoom": "Zoom zurücksetzen",
"view.title": "Ansicht",
"view.toggleFullscreen": "Vollbild umschalten",
"view.zoomIn": "Vergrößern",
"view.zoomOut": "Verkleinern",
"window.bringAllToFront": "Alle Fenster in den Vordergrund bringen",
"window.close": "Schließen",
"window.front": "Alle Fenster in den Vordergrund bringen",
"window.minimize": "Minimieren",
"window.title": "Fenster",
"window.toggleFullscreen": "Vollbild umschalten",
"window.zoom": "Zoom"
}
@@ -1,32 +0,0 @@
{
"actions": {
"add": "Add",
"back": "Back",
"cancel": "Cancel",
"close": "Close",
"confirm": "Confirm",
"delete": "Delete",
"edit": "Edit",
"more": "More",
"next": "Next",
"ok": "OK",
"previous": "Previous",
"refresh": "Refresh",
"remove": "Remove",
"retry": "Retry",
"save": "Save",
"search": "Search",
"submit": "Submit"
},
"app": {
"description": "Your AI Assistant Collaboration Platform",
"name": "LobeHub"
},
"status": {
"error": "Error",
"info": "Information",
"loading": "Loading",
"success": "Success",
"warning": "Warning"
}
}
@@ -1,31 +0,0 @@
{
"about": {
"button": "OK",
"detail": "A chat application based on a large language model",
"message": "{{appName}} {{appVersion}}",
"title": "About"
},
"confirm": {
"cancel": "Cancel",
"no": "No",
"title": "Confirm",
"yes": "Yes"
},
"error": {
"button": "OK",
"detail": "An error occurred during the operation, please try again later",
"message": "An error occurred",
"title": "Error"
},
"update": {
"downloadAndInstall": "Download and Install",
"downloadComplete": "Download Complete",
"downloadCompleteMessage": "The update package has been downloaded, would you like to install it now?",
"installLater": "Install Later",
"installNow": "Install Now",
"later": "Remind Me Later",
"newVersion": "New Version Found",
"newVersionAvailable": "New version available: {{version}}",
"skipThisVersion": "Skip This Version"
}
}
@@ -1,71 +0,0 @@
{
"common": {
"checkUpdates": "Checking for updates..."
},
"dev": {
"devPanel": "Developer Panel",
"devTools": "Developer Tools",
"forceReload": "Force Reload",
"openStore": "Open Storage File",
"refreshMenu": "Refresh menu",
"reload": "Reload",
"title": "Development"
},
"edit": {
"copy": "Copy",
"cut": "Cut",
"delete": "Delete",
"paste": "Paste",
"redo": "Redo",
"selectAll": "Select All",
"speech": "Speech",
"startSpeaking": "Start Speaking",
"stopSpeaking": "Stop Speaking",
"title": "Edit",
"undo": "Undo"
},
"file": {
"preferences": "Preferences",
"quit": "Quit",
"title": "File"
},
"help": {
"about": "About",
"githubRepo": "GitHub Repository",
"reportIssue": "Report Issue",
"title": "Help",
"visitWebsite": "Visit Website"
},
"macOS": {
"about": "About {{appName}}",
"devTools": "LobeHub Developer Tools",
"hide": "Hide {{appName}}",
"hideOthers": "Hide Others",
"preferences": "Preferences...",
"services": "Services",
"unhide": "Show All"
},
"tray": {
"open": "Open {{appName}}",
"quit": "Quit",
"show": "Show {{appName}}"
},
"view": {
"forceReload": "Force Reload",
"reload": "Reload",
"resetZoom": "Reset Zoom",
"title": "View",
"toggleFullscreen": "Toggle Fullscreen",
"zoomIn": "Zoom In",
"zoomOut": "Zoom Out"
},
"window": {
"bringAllToFront": "Bring All Windows to Front",
"close": "Close",
"front": "Bring All Windows to Front",
"minimize": "Minimize",
"title": "Window",
"toggleFullscreen": "Toggle Fullscreen",
"zoom": "Zoom"
}
}
@@ -1,32 +1,26 @@
{
"actions": {
"add": "Agregar",
"back": "Volver",
"cancel": "Cancelar",
"close": "Cerrar",
"confirm": "Confirmar",
"delete": "Eliminar",
"edit": "Editar",
"more": "Más",
"next": "Siguiente",
"ok": "Aceptar",
"previous": "Anterior",
"refresh": "Actualizar",
"remove": "Eliminar",
"retry": "Reintentar",
"save": "Guardar",
"search": "Buscar",
"submit": "Enviar"
},
"app": {
"description": "Tu plataforma de colaboración con el asistente de IA",
"name": "LobeHub"
},
"status": {
"error": "Error",
"info": "Información",
"loading": "Cargando",
"success": "Éxito",
"warning": "Advertencia"
}
}
"actions.add": "Agregar",
"actions.back": "Volver",
"actions.cancel": "Cancelar",
"actions.close": "Cerrar",
"actions.confirm": "Confirmar",
"actions.delete": "Eliminar",
"actions.edit": "Editar",
"actions.more": "Más",
"actions.next": "Siguiente",
"actions.ok": "Aceptar",
"actions.previous": "Anterior",
"actions.refresh": "Actualizar",
"actions.remove": "Eliminar",
"actions.retry": "Reintentar",
"actions.save": "Guardar",
"actions.search": "Buscar",
"actions.submit": "Enviar",
"app.description": "Tu plataforma de colaboración con el asistente de IA",
"app.name": "LobeHub",
"status.error": "Error",
"status.info": "Información",
"status.loading": "Cargando",
"status.success": "Éxito",
"status.warning": "Advertencia"
}
@@ -1,31 +1,23 @@
{
"about": {
"button": "Aceptar",
"detail": "Una aplicación de chat basada en un modelo de lenguaje grande",
"message": "{{appName}} {{appVersion}}",
"title": "Acerca de"
},
"confirm": {
"cancel": "Cancelar",
"no": "No",
"title": "Confirmar",
"yes": "Sí"
},
"error": {
"button": "Aceptar",
"detail": "Se produjo un error durante la operación, por favor intente de nuevo más tarde",
"message": "Se produjo un error",
"title": "Error"
},
"update": {
"downloadAndInstall": "Descargar e instalar",
"downloadComplete": "Descarga completada",
"downloadCompleteMessage": "El paquete de actualización se ha descargado, ¿desea instalarlo ahora?",
"installLater": "Instalar más tarde",
"installNow": "Instalar ahora",
"later": "Recordar más tarde",
"newVersion": "Nueva versión disponible",
"newVersionAvailable": "Nueva versión encontrada: {{version}}",
"skipThisVersion": "Saltar esta versión"
}
}
"about.button": "Aceptar",
"about.detail": "Una aplicación de chat basada en un modelo de lenguaje grande",
"about.message": "{{appName}} {{appVersion}}",
"about.title": "Acerca de",
"confirm.cancel": "Cancelar",
"confirm.no": "No",
"confirm.title": "Confirmar",
"confirm.yes": "Sí",
"error.button": "Aceptar",
"error.detail": "Se produjo un error durante la operación, por favor intente de nuevo más tarde",
"error.message": "Se produjo un error",
"error.title": "Error",
"update.downloadAndInstall": "Descargar e instalar",
"update.downloadComplete": "Descarga completada",
"update.downloadCompleteMessage": "El paquete de actualización se ha descargado, ¿desea instalarlo ahora?",
"update.installLater": "Instalar más tarde",
"update.installNow": "Instalar ahora",
"update.later": "Recordar más tarde",
"update.newVersion": "Nueva versión disponible",
"update.newVersionAvailable": "Nueva versión encontrada: {{version}}",
"update.skipThisVersion": "Saltar esta versión"
}
+52 -70
View File
@@ -1,71 +1,53 @@
{
"common": {
"checkUpdates": "Comprobando actualizaciones..."
},
"dev": {
"devPanel": "Panel de desarrollador",
"devTools": "Herramientas de desarrollador",
"forceReload": "Recargar forzosamente",
"openStore": "Abrir archivo de almacenamiento",
"refreshMenu": "Actualizar menú",
"reload": "Recargar",
"title": "Desarrollo"
},
"edit": {
"copy": "Copiar",
"cut": "Cortar",
"delete": "Eliminar",
"paste": "Pegar",
"redo": "Rehacer",
"selectAll": "Seleccionar todo",
"speech": "Voz",
"startSpeaking": "Comenzar a leer en voz alta",
"stopSpeaking": "Detener lectura en voz alta",
"title": "Editar",
"undo": "Deshacer"
},
"file": {
"preferences": "Preferencias",
"quit": "Salir",
"title": "Archivo"
},
"help": {
"about": "Acerca de",
"githubRepo": "Repositorio de GitHub",
"reportIssue": "Reportar un problema",
"title": "Ayuda",
"visitWebsite": "Visitar el sitio web"
},
"macOS": {
"about": "Acerca de {{appName}}",
"devTools": "Herramientas de desarrollador de LobeHub",
"hide": "Ocultar {{appName}}",
"hideOthers": "Ocultar otros",
"preferences": "Configuración...",
"services": "Servicios",
"unhide": "Mostrar todo"
},
"tray": {
"open": "Abrir {{appName}}",
"quit": "Salir",
"show": "Mostrar {{appName}}"
},
"view": {
"forceReload": "Recargar forzosamente",
"reload": "Recargar",
"resetZoom": "Restablecer zoom",
"title": "Vista",
"toggleFullscreen": "Alternar pantalla completa",
"zoomIn": "Acercar",
"zoomOut": "Alejar"
},
"window": {
"bringAllToFront": "Traer todas las ventanas al frente",
"close": "Cerrar",
"front": "Traer todas las ventanas al frente",
"minimize": "Minimizar",
"title": "Ventana",
"toggleFullscreen": "Alternar pantalla completa",
"zoom": "Zoom"
}
}
"common.checkUpdates": "Comprobando actualizaciones...",
"dev.devPanel": "Panel de desarrollador",
"dev.devTools": "Herramientas de desarrollador",
"dev.forceReload": "Recargar forzosamente",
"dev.openStore": "Abrir archivo de almacenamiento",
"dev.refreshMenu": "Actualizar menú",
"dev.reload": "Recargar",
"dev.title": "Desarrollo",
"edit.copy": "Copiar",
"edit.cut": "Cortar",
"edit.delete": "Eliminar",
"edit.paste": "Pegar",
"edit.redo": "Rehacer",
"edit.selectAll": "Seleccionar todo",
"edit.speech": "Voz",
"edit.startSpeaking": "Comenzar a leer en voz alta",
"edit.stopSpeaking": "Detener lectura en voz alta",
"edit.title": "Editar",
"edit.undo": "Deshacer",
"file.preferences": "Preferencias",
"file.quit": "Salir",
"file.title": "Archivo",
"help.about": "Acerca de",
"help.githubRepo": "Repositorio de GitHub",
"help.reportIssue": "Reportar un problema",
"help.title": "Ayuda",
"help.visitWebsite": "Visitar el sitio web",
"macOS.about": "Acerca de {{appName}}",
"macOS.devTools": "Herramientas de desarrollador de LobeHub",
"macOS.hide": "Ocultar {{appName}}",
"macOS.hideOthers": "Ocultar otros",
"macOS.preferences": "Configuración...",
"macOS.services": "Servicios",
"macOS.unhide": "Mostrar todo",
"tray.open": "Abrir {{appName}}",
"tray.quit": "Salir",
"tray.show": "Mostrar {{appName}}",
"view.forceReload": "Recargar forzosamente",
"view.reload": "Recargar",
"view.resetZoom": "Restablecer zoom",
"view.title": "Vista",
"view.toggleFullscreen": "Alternar pantalla completa",
"view.zoomIn": "Acercar",
"view.zoomOut": "Alejar",
"window.bringAllToFront": "Traer todas las ventanas al frente",
"window.close": "Cerrar",
"window.front": "Traer todas las ventanas al frente",
"window.minimize": "Minimizar",
"window.title": "Ventana",
"window.toggleFullscreen": "Alternar pantalla completa",
"window.zoom": "Zoom"
}
@@ -1,32 +1,26 @@
{
"actions": {
"add": "افزودن",
"back": "بازگشت",
"cancel": "لغو",
"close": "بستن",
"confirm": "تأیید",
"delete": "حذف",
"edit": "ویرایش",
"more": "بیشتر",
"next": "مرحله بعد",
"ok": "تأیید",
"previous": "مرحله قبل",
"refresh": "به‌روزرسانی",
"remove": "حذف",
"retry": "تلاش مجدد",
"save": "ذخیره",
"search": "جستجو",
"submit": "ارسال"
},
"app": {
"description": "پلتفرم همکاری دستیار هوش مصنوعی شما",
"name": "LobeHub"
},
"status": {
"error": "خطا",
"info": "اطلاعات",
"loading": "در حال بارگذاری",
"success": "موفق",
"warning": "هشدار"
}
}
"actions.add": "افزودن",
"actions.back": "بازگشت",
"actions.cancel": "لغو",
"actions.close": "بستن",
"actions.confirm": "تأیید",
"actions.delete": "حذف",
"actions.edit": "ویرایش",
"actions.more": "بیشتر",
"actions.next": "مرحله بعد",
"actions.ok": "تأیید",
"actions.previous": "مرحله قبل",
"actions.refresh": "به‌روزرسانی",
"actions.remove": "حذف",
"actions.retry": "تلاش مجدد",
"actions.save": "ذخیره",
"actions.search": "جستجو",
"actions.submit": "ارسال",
"app.description": "پلتفرم همکاری دستیار هوش مصنوعی شما",
"app.name": "LobeHub",
"status.error": "خطا",
"status.info": "اطلاعات",
"status.loading": "در حال بارگذاری",
"status.success": "موفق",
"status.warning": "هشدار"
}
@@ -1,31 +1,23 @@
{
"about": {
"button": "تأیید",
"detail": "یک برنامه چت مبتنی بر مدل‌های زبانی بزرگ",
"message": "{{appName}} {{appVersion}}",
"title": "درباره"
},
"confirm": {
"cancel": "لغو",
"no": "خیر",
"title": "تأیید",
"yes": "بله"
},
"error": {
"button": "تأیید",
"detail": "در حین انجام عملیات خطایی رخ داده است، لطفاً بعداً دوباره تلاش کنید",
"message": "خطا رخ داده است",
"title": "خطا"
},
"update": {
"downloadAndInstall": "دانلود و نصب",
"downloadComplete": "دانلود کامل شد",
"downloadCompleteMessage": "بسته به‌روزرسانی دانلود شده است، آیا می‌خواهید بلافاصله نصب کنید؟",
"installLater": "نصب بعداً",
"installNow": "نصب اکنون",
"later": "یادآوری بعداً",
"newVersion": "نسخه جدیدی پیدا شد",
"newVersionAvailable": "نسخه جدید پیدا شد: {{version}}",
"skipThisVersion": "این نسخه را نادیده بگیرید"
}
}
"about.button": "تأیید",
"about.detail": "یک برنامه چت مبتنی بر مدل‌های زبانی بزرگ",
"about.message": "{{appName}} {{appVersion}}",
"about.title": "درباره",
"confirm.cancel": "لغو",
"confirm.no": "خیر",
"confirm.title": "تأیید",
"confirm.yes": "بله",
"error.button": "تأیید",
"error.detail": "در حین انجام عملیات خطایی رخ داده است، لطفاً بعداً دوباره تلاش کنید",
"error.message": "خطا رخ داده است",
"error.title": "خطا",
"update.downloadAndInstall": "دانلود و نصب",
"update.downloadComplete": "دانلود کامل شد",
"update.downloadCompleteMessage": "بسته به‌روزرسانی دانلود شده است، آیا می‌خواهید بلافاصله نصب کنید؟",
"update.installLater": "نصب بعداً",
"update.installNow": "نصب اکنون",
"update.later": "یادآوری بعداً",
"update.newVersion": "نسخه جدیدی پیدا شد",
"update.newVersionAvailable": "نسخه جدید پیدا شد: {{version}}",
"update.skipThisVersion": "این نسخه را نادیده بگیرید"
}
+52 -70
View File
@@ -1,71 +1,53 @@
{
"common": {
"checkUpdates": "بررسی به‌روزرسانی..."
},
"dev": {
"devPanel": "پنل توسعه‌دهنده",
"devTools": "ابزارهای توسعه‌دهنده",
"forceReload": "بارگذاری اجباری",
"openStore": "باز کردن فایل‌های ذخیره شده",
"refreshMenu": "به‌روزرسانی منو",
"reload": ارگذاری مجدد",
"title": "توسعه"
},
"edit": {
"copy": "کپی",
"cut": "برش",
"delete": "حذف",
"paste": "چسباندن",
"redo": "انجام مجدد",
"selectAll": "انتخاب همه",
"speech": "گفتار",
"startSpeaking": "شروع به خواندن",
"stopSpeaking": "متوقف کردن خواندن",
"title": "ویرایش",
"undo": "بازگشت"
},
"file": {
"preferences": "تنظیمات",
"quit": "خروج",
"title": "فایل"
},
"help": {
"about": "درباره",
"githubRepo": "مخزن GitHub",
"reportIssue": "گزارش مشکل",
"title": "کمک",
"visitWebsite": "بازدید از وب‌سایت"
},
"macOS": {
"about": "درباره {{appName}}",
"devTools": "ابزارهای توسعه‌دهنده LobeHub",
"hide": "پنهان کردن {{appName}}",
"hideOthers": "پنهان کردن دیگران",
"preferences": "تنظیمات...",
"services": "خدمات",
"unhide": "نمایش همه"
},
"tray": {
"open": "باز کردن {{appName}}",
"quit": "خروج",
"show": "نمایش {{appName}}"
},
"view": {
"forceReload": "بارگذاری اجباری",
"reload": "بارگذاری مجدد",
"resetZoom": "تنظیم زوم به حالت اولیه",
"title": "نمایش",
"toggleFullscreen": "تغییر به حالت تمام صفحه",
"zoomIn": "بزرگ‌نمایی",
"zoomOut": "کوچک‌نمایی"
},
"window": {
"bringAllToFront": "همه پنجره‌ها را به جلو بیاورید",
"close": "بستن",
"front": "همه پنجره‌ها را به جلو بیاورید",
"minimize": "کوچک کردن",
"title": "پنجره",
"toggleFullscreen": "تغییر به حالت تمام صفحه",
"zoom": "زوم"
}
}
"common.checkUpdates": "بررسی به‌روزرسانی...",
"dev.devPanel": "پنل توسعه‌دهنده",
"dev.devTools": "ابزارهای توسعه‌دهنده",
"dev.forceReload": "بارگذاری اجباری",
"dev.openStore": "باز کردن فایل‌های ذخیره شده",
"dev.refreshMenu": "به‌روزرسانی منو",
"dev.reload": "بارگذاری مجدد",
"dev.title": "توسعه",
"edit.copy": "کپی",
"edit.cut": رش",
"edit.delete": "حذف",
"edit.paste": "چسباندن",
"edit.redo": "انجام مجدد",
"edit.selectAll": "انتخاب همه",
"edit.speech": "گفتار",
"edit.startSpeaking": "شروع به خواندن",
"edit.stopSpeaking": "متوقف کردن خواندن",
"edit.title": "ویرایش",
"edit.undo": "بازگشت",
"file.preferences": "تنظیمات",
"file.quit": "خروج",
"file.title": "فایل",
"help.about": "درباره",
"help.githubRepo": "مخزن GitHub",
"help.reportIssue": "گزارش مشکل",
"help.title": "کمک",
"help.visitWebsite": "بازدید از وب‌سایت",
"macOS.about": "درباره {{appName}}",
"macOS.devTools": "ابزارهای توسعه‌دهنده LobeHub",
"macOS.hide": "پنهان کردن {{appName}}",
"macOS.hideOthers": "پنهان کردن دیگران",
"macOS.preferences": "تنظیمات...",
"macOS.services": "خدمات",
"macOS.unhide": "نمایش همه",
"tray.open": "باز کردن {{appName}}",
"tray.quit": "خروج",
"tray.show": "نمایش {{appName}}",
"view.forceReload": "بارگذاری اجباری",
"view.reload": "بارگذاری مجدد",
"view.resetZoom": "تنظیم زوم به حالت اولیه",
"view.title": "نمایش",
"view.toggleFullscreen": "تغییر به حالت تمام صفحه",
"view.zoomIn": "بزرگ‌نمایی",
"view.zoomOut": "کوچک‌نمایی",
"window.bringAllToFront": "همه پنجره‌ها را به جلو بیاورید",
"window.close": "بستن",
"window.front": "همه پنجره‌ها را به جلو بیاورید",
"window.minimize": "کوچک کردن",
"window.title": "پنجره",
"window.toggleFullscreen": "تغییر به حالت تمام صفحه",
"window.zoom": "زوم"
}
@@ -1,32 +1,26 @@
{
"actions": {
"add": "Ajouter",
"back": "Retour",
"cancel": "Annuler",
"close": "Fermer",
"confirm": "Confirmer",
"delete": "Supprimer",
"edit": "Éditer",
"more": "Plus",
"next": "Suivant",
"ok": "D'accord",
"previous": "Précédent",
"refresh": "Rafraîchir",
"remove": "Retirer",
"retry": "Réessayer",
"save": "Enregistrer",
"search": "Rechercher",
"submit": "Soumettre"
},
"app": {
"description": "Votre plateforme de collaboration avec l'assistant IA",
"name": "LobeHub"
},
"status": {
"error": "Erreur",
"info": "Information",
"loading": "Chargement",
"success": "Succès",
"warning": "Avertissement"
}
}
"actions.add": "Ajouter",
"actions.back": "Retour",
"actions.cancel": "Annuler",
"actions.close": "Fermer",
"actions.confirm": "Confirmer",
"actions.delete": "Supprimer",
"actions.edit": "Éditer",
"actions.more": "Plus",
"actions.next": "Suivant",
"actions.ok": "D'accord",
"actions.previous": "Précédent",
"actions.refresh": "Rafraîchir",
"actions.remove": "Retirer",
"actions.retry": "Réessayer",
"actions.save": "Enregistrer",
"actions.search": "Rechercher",
"actions.submit": "Soumettre",
"app.description": "Votre plateforme de collaboration avec l'assistant IA",
"app.name": "LobeHub",
"status.error": "Erreur",
"status.info": "Information",
"status.loading": "Chargement",
"status.success": "Succès",
"status.warning": "Avertissement"
}
@@ -1,31 +1,23 @@
{
"about": {
"button": "D'accord",
"detail": "Une application de chat basée sur un grand modèle de langage",
"message": "{{appName}} {{appVersion}}",
"title": "À propos"
},
"confirm": {
"cancel": "Annuler",
"no": "Non",
"title": "Confirmer",
"yes": "Oui"
},
"error": {
"button": "D'accord",
"detail": "Une erreur s'est produite lors de l'opération, veuillez réessayer plus tard",
"message": "Une erreur s'est produite",
"title": "Erreur"
},
"update": {
"downloadAndInstall": "Télécharger et installer",
"downloadComplete": "Téléchargement terminé",
"downloadCompleteMessage": "Le paquet de mise à jour a été téléchargé, souhaitez-vous l'installer maintenant ?",
"installLater": "Installer plus tard",
"installNow": "Installer maintenant",
"later": "Rappeler plus tard",
"newVersion": "Nouvelle version détectée",
"newVersionAvailable": "Nouvelle version disponible : {{version}}",
"skipThisVersion": "Ignorer cette version"
}
}
"about.button": "D'accord",
"about.detail": "Une application de chat basée sur un grand modèle de langage",
"about.message": "{{appName}} {{appVersion}}",
"about.title": "À propos",
"confirm.cancel": "Annuler",
"confirm.no": "Non",
"confirm.title": "Confirmer",
"confirm.yes": "Oui",
"error.button": "D'accord",
"error.detail": "Une erreur s'est produite lors de l'opération, veuillez réessayer plus tard",
"error.message": "Une erreur s'est produite",
"error.title": "Erreur",
"update.downloadAndInstall": "Télécharger et installer",
"update.downloadComplete": "Téléchargement terminé",
"update.downloadCompleteMessage": "Le paquet de mise à jour a été téléchargé, souhaitez-vous l'installer maintenant ?",
"update.installLater": "Installer plus tard",
"update.installNow": "Installer maintenant",
"update.later": "Rappeler plus tard",
"update.newVersion": "Nouvelle version détectée",
"update.newVersionAvailable": "Nouvelle version disponible : {{version}}",
"update.skipThisVersion": "Ignorer cette version"
}
+52 -70
View File
@@ -1,71 +1,53 @@
{
"common": {
"checkUpdates": "Vérifier les mises à jour..."
},
"dev": {
"devPanel": "Panneau de développement",
"devTools": "Outils de développement",
"forceReload": "Recharger de force",
"openStore": "Ouvrir le fichier de stockage",
"refreshMenu": "Rafraîchir le menu",
"reload": "Recharger",
"title": "Développement"
},
"edit": {
"copy": "Copier",
"cut": "Couper",
"delete": "Supprimer",
"paste": "Coller",
"redo": "Rétablir",
"selectAll": "Tout sélectionner",
"speech": "Voix",
"startSpeaking": "Commencer à lire",
"stopSpeaking": "Arrêter de lire",
"title": "Édition",
"undo": "Annuler"
},
"file": {
"preferences": "Préférences",
"quit": "Quitter",
"title": "Fichier"
},
"help": {
"about": "À propos",
"githubRepo": "Dépôt GitHub",
"reportIssue": "Signaler un problème",
"title": "Aide",
"visitWebsite": "Visiter le site officiel"
},
"macOS": {
"about": "À propos de {{appName}}",
"devTools": "Outils de développement LobeHub",
"hide": "Masquer {{appName}}",
"hideOthers": "Masquer les autres",
"preferences": "Préférences...",
"services": "Services",
"unhide": "Tout afficher"
},
"tray": {
"open": "Ouvrir {{appName}}",
"quit": "Quitter",
"show": "Afficher {{appName}}"
},
"view": {
"forceReload": "Recharger de force",
"reload": "Recharger",
"resetZoom": "Réinitialiser le zoom",
"title": "Affichage",
"toggleFullscreen": "Basculer en plein écran",
"zoomIn": "Zoomer",
"zoomOut": "Dézoomer"
},
"window": {
"bringAllToFront": "Mettre toutes les fenêtres au premier plan",
"close": "Fermer",
"front": "Mettre toutes les fenêtres au premier plan",
"minimize": "Réduire",
"title": "Fenêtre",
"toggleFullscreen": "Basculer en plein écran",
"zoom": "Zoom"
}
}
"common.checkUpdates": "Vérifier les mises à jour...",
"dev.devPanel": "Panneau de développement",
"dev.devTools": "Outils de développement",
"dev.forceReload": "Recharger de force",
"dev.openStore": "Ouvrir le fichier de stockage",
"dev.refreshMenu": "Rafraîchir le menu",
"dev.reload": "Recharger",
"dev.title": "Développement",
"edit.copy": "Copier",
"edit.cut": "Couper",
"edit.delete": "Supprimer",
"edit.paste": "Coller",
"edit.redo": "Rétablir",
"edit.selectAll": "Tout sélectionner",
"edit.speech": "Voix",
"edit.startSpeaking": "Commencer à lire",
"edit.stopSpeaking": "Arrêter de lire",
"edit.title": "Édition",
"edit.undo": "Annuler",
"file.preferences": "Préférences",
"file.quit": "Quitter",
"file.title": "Fichier",
"help.about": "À propos",
"help.githubRepo": "Dépôt GitHub",
"help.reportIssue": "Signaler un problème",
"help.title": "Aide",
"help.visitWebsite": "Visiter le site officiel",
"macOS.about": "À propos de {{appName}}",
"macOS.devTools": "Outils de développement LobeHub",
"macOS.hide": "Masquer {{appName}}",
"macOS.hideOthers": "Masquer les autres",
"macOS.preferences": "Préférences...",
"macOS.services": "Services",
"macOS.unhide": "Tout afficher",
"tray.open": "Ouvrir {{appName}}",
"tray.quit": "Quitter",
"tray.show": "Afficher {{appName}}",
"view.forceReload": "Recharger de force",
"view.reload": "Recharger",
"view.resetZoom": "Réinitialiser le zoom",
"view.title": "Affichage",
"view.toggleFullscreen": "Basculer en plein écran",
"view.zoomIn": "Zoomer",
"view.zoomOut": "Dézoomer",
"window.bringAllToFront": "Mettre toutes les fenêtres au premier plan",
"window.close": "Fermer",
"window.front": "Mettre toutes les fenêtres au premier plan",
"window.minimize": "Réduire",
"window.title": "Fenêtre",
"window.toggleFullscreen": "Basculer en plein écran",
"window.zoom": "Zoom"
}
@@ -1,32 +1,26 @@
{
"actions": {
"add": "Aggiungi",
"back": "Indietro",
"cancel": "Annulla",
"close": "Chiudi",
"confirm": "Conferma",
"delete": "Elimina",
"edit": "Modifica",
"more": "Di più",
"next": "Avanti",
"ok": "OK",
"previous": "Indietro",
"refresh": "Aggiorna",
"remove": "Rimuovi",
"retry": "Riprova",
"save": "Salva",
"search": "Cerca",
"submit": "Invia"
},
"app": {
"description": "La tua piattaforma di collaborazione con assistente AI",
"name": "LobeHub"
},
"status": {
"error": "Errore",
"info": "Informazioni",
"loading": "Caricamento in corso",
"success": "Successo",
"warning": "Avviso"
}
}
"actions.add": "Aggiungi",
"actions.back": "Indietro",
"actions.cancel": "Annulla",
"actions.close": "Chiudi",
"actions.confirm": "Conferma",
"actions.delete": "Elimina",
"actions.edit": "Modifica",
"actions.more": "Di più",
"actions.next": "Avanti",
"actions.ok": "OK",
"actions.previous": "Indietro",
"actions.refresh": "Aggiorna",
"actions.remove": "Rimuovi",
"actions.retry": "Riprova",
"actions.save": "Salva",
"actions.search": "Cerca",
"actions.submit": "Invia",
"app.description": "La tua piattaforma di collaborazione con assistente AI",
"app.name": "LobeHub",
"status.error": "Errore",
"status.info": "Informazioni",
"status.loading": "Caricamento in corso",
"status.success": "Successo",
"status.warning": "Avviso"
}
@@ -1,31 +1,23 @@
{
"about": {
"button": "Conferma",
"detail": "Un'app di chat basata su un grande modello linguistico",
"message": "{{appName}} {{appVersion}}",
"title": "Informazioni"
},
"confirm": {
"cancel": "Annulla",
"no": "No",
"title": "Conferma",
"yes": "Sì"
},
"error": {
"button": "Conferma",
"detail": "Si è verificato un errore durante l'operazione, riprovare più tardi",
"message": "Si è verificato un errore",
"title": "Errore"
},
"update": {
"downloadAndInstall": "Scarica e installa",
"downloadComplete": "Download completato",
"downloadCompleteMessage": "Il pacchetto di aggiornamento è stato scaricato, vuoi installarlo subito?",
"installLater": "Installa più tardi",
"installNow": "Installa ora",
"later": "Promemoria più tardi",
"newVersion": "Nuova versione disponibile",
"newVersionAvailable": "Nuova versione trovata: {{version}}",
"skipThisVersion": "Salta questa versione"
}
}
"about.button": "Conferma",
"about.detail": "Un'app di chat basata su un grande modello linguistico",
"about.message": "{{appName}} {{appVersion}}",
"about.title": "Informazioni",
"confirm.cancel": "Annulla",
"confirm.no": "No",
"confirm.title": "Conferma",
"confirm.yes": "",
"error.button": "Conferma",
"error.detail": "Si è verificato un errore durante l'operazione, riprovare più tardi",
"error.message": "Si è verificato un errore",
"error.title": "Errore",
"update.downloadAndInstall": "Scarica e installa",
"update.downloadComplete": "Download completato",
"update.downloadCompleteMessage": "Il pacchetto di aggiornamento è stato scaricato, vuoi installarlo subito?",
"update.installLater": "Installa più tardi",
"update.installNow": "Installa ora",
"update.later": "Promemoria più tardi",
"update.newVersion": "Nuova versione disponibile",
"update.newVersionAvailable": "Nuova versione trovata: {{version}}",
"update.skipThisVersion": "Salta questa versione"
}
+52 -70
View File
@@ -1,71 +1,53 @@
{
"common": {
"checkUpdates": "Controlla aggiornamenti..."
},
"dev": {
"devPanel": "Pannello sviluppatore",
"devTools": "Strumenti per sviluppatori",
"forceReload": "Ricarica forzata",
"openStore": "Apri il file di archiviazione",
"refreshMenu": "Aggiorna menu",
"reload": "Ricarica",
"title": "Sviluppo"
},
"edit": {
"copy": "Copia",
"cut": "Taglia",
"delete": "Elimina",
"paste": "Incolla",
"redo": "Ripeti",
"selectAll": "Seleziona tutto",
"speech": "Voce",
"startSpeaking": "Inizia a leggere",
"stopSpeaking": "Ferma la lettura",
"title": "Modifica",
"undo": "Annulla"
},
"file": {
"preferences": "Preferenze",
"quit": "Esci",
"title": "File"
},
"help": {
"about": "Informazioni",
"githubRepo": "Repository GitHub",
"reportIssue": "Segnala un problema",
"title": "Aiuto",
"visitWebsite": "Visita il sito ufficiale"
},
"macOS": {
"about": "Informazioni su {{appName}}",
"devTools": "Strumenti per sviluppatori LobeHub",
"hide": "Nascondi {{appName}}",
"hideOthers": "Nascondi altri",
"preferences": "Impostazioni...",
"services": "Servizi",
"unhide": "Mostra tutto"
},
"tray": {
"open": "Apri {{appName}}",
"quit": "Esci",
"show": "Mostra {{appName}}"
},
"view": {
"forceReload": "Ricarica forzata",
"reload": "Ricarica",
"resetZoom": "Reimposta zoom",
"title": "Visualizza",
"toggleFullscreen": "Attiva/disattiva schermo intero",
"zoomIn": "Ingrandisci",
"zoomOut": "Riduci"
},
"window": {
"bringAllToFront": "Porta tutte le finestre in primo piano",
"close": "Chiudi",
"front": "Porta tutte le finestre in primo piano",
"minimize": "Minimizza",
"title": "Finestra",
"toggleFullscreen": "Attiva/disattiva schermo intero",
"zoom": "Zoom"
}
}
"common.checkUpdates": "Controlla aggiornamenti...",
"dev.devPanel": "Pannello sviluppatore",
"dev.devTools": "Strumenti per sviluppatori",
"dev.forceReload": "Ricarica forzata",
"dev.openStore": "Apri il file di archiviazione",
"dev.refreshMenu": "Aggiorna menu",
"dev.reload": "Ricarica",
"dev.title": "Sviluppo",
"edit.copy": "Copia",
"edit.cut": "Taglia",
"edit.delete": "Elimina",
"edit.paste": "Incolla",
"edit.redo": "Ripeti",
"edit.selectAll": "Seleziona tutto",
"edit.speech": "Voce",
"edit.startSpeaking": "Inizia a leggere",
"edit.stopSpeaking": "Ferma la lettura",
"edit.title": "Modifica",
"edit.undo": "Annulla",
"file.preferences": "Preferenze",
"file.quit": "Esci",
"file.title": "File",
"help.about": "Informazioni",
"help.githubRepo": "Repository GitHub",
"help.reportIssue": "Segnala un problema",
"help.title": "Aiuto",
"help.visitWebsite": "Visita il sito ufficiale",
"macOS.about": "Informazioni su {{appName}}",
"macOS.devTools": "Strumenti per sviluppatori LobeHub",
"macOS.hide": "Nascondi {{appName}}",
"macOS.hideOthers": "Nascondi altri",
"macOS.preferences": "Impostazioni...",
"macOS.services": "Servizi",
"macOS.unhide": "Mostra tutto",
"tray.open": "Apri {{appName}}",
"tray.quit": "Esci",
"tray.show": "Mostra {{appName}}",
"view.forceReload": "Ricarica forzata",
"view.reload": "Ricarica",
"view.resetZoom": "Reimposta zoom",
"view.title": "Visualizza",
"view.toggleFullscreen": "Attiva/disattiva schermo intero",
"view.zoomIn": "Ingrandisci",
"view.zoomOut": "Riduci",
"window.bringAllToFront": "Porta tutte le finestre in primo piano",
"window.close": "Chiudi",
"window.front": "Porta tutte le finestre in primo piano",
"window.minimize": "Minimizza",
"window.title": "Finestra",
"window.toggleFullscreen": "Attiva/disattiva schermo intero",
"window.zoom": "Zoom"
}
@@ -1,32 +1,26 @@
{
"actions": {
"add": "追加",
"back": "戻る",
"cancel": "キャンセル",
"close": "閉じる",
"confirm": "確認",
"delete": "削除",
"edit": "編集",
"more": "もっと見る",
"next": "次へ",
"ok": "OK",
"previous": "前へ",
"refresh": "更新",
"remove": "削除",
"retry": "再試行",
"save": "保存",
"search": "検索",
"submit": "送信"
},
"app": {
"description": "あなたのAIアシスタント協力プラットフォーム",
"name": "LobeHub"
},
"status": {
"error": "エラー",
"info": "情報",
"loading": "読み込み中",
"success": "成功",
"warning": "警告"
}
}
"actions.add": "追加",
"actions.back": "戻る",
"actions.cancel": "キャンセル",
"actions.close": "閉じる",
"actions.confirm": "確認",
"actions.delete": "削除",
"actions.edit": "編集",
"actions.more": "もっと見る",
"actions.next": "次へ",
"actions.ok": "OK",
"actions.previous": "前へ",
"actions.refresh": "更新",
"actions.remove": "削除",
"actions.retry": "再試行",
"actions.save": "保存",
"actions.search": "検索",
"actions.submit": "送信",
"app.description": "あなたのAIアシスタント協力プラットフォーム",
"app.name": "LobeHub",
"status.error": "エラー",
"status.info": "情報",
"status.loading": "読み込み中",
"status.success": "成功",
"status.warning": "警告"
}
@@ -1,31 +1,23 @@
{
"about": {
"button": "確定",
"detail": "大規模言語モデルに基づくチャットアプリ",
"message": "{{appName}} {{appVersion}}",
"title": "について"
},
"confirm": {
"cancel": "キャンセル",
"no": "いいえ",
"title": "確認",
"yes": "はい"
},
"error": {
"button": "確定",
"detail": "操作中にエラーが発生しました。後で再試行してください。",
"message": "エラーが発生しました",
"title": "エラー"
},
"update": {
"downloadAndInstall": "ダウンロードしてインストール",
"downloadComplete": "ダウンロード完了",
"downloadCompleteMessage": "更新パッケージのダウンロードが完了しました。今すぐインストールしますか?",
"installLater": "後でインストール",
"installNow": "今すぐインストール",
"later": "後でリマインド",
"newVersion": "新しいバージョンが見つかりました",
"newVersionAvailable": "新しいバージョンが見つかりました: {{version}}",
"skipThisVersion": "このバージョンをスキップ"
}
}
"about.button": "確定",
"about.detail": "大規模言語モデルに基づくチャットアプリ",
"about.message": "{{appName}} {{appVersion}}",
"about.title": "について",
"confirm.cancel": "キャンセル",
"confirm.no": "いいえ",
"confirm.title": "確認",
"confirm.yes": "はい",
"error.button": "確定",
"error.detail": "操作中にエラーが発生しました。後で再試行してください。",
"error.message": "エラーが発生しました",
"error.title": "エラー",
"update.downloadAndInstall": "ダウンロードしてインストール",
"update.downloadComplete": "ダウンロード完了",
"update.downloadCompleteMessage": "更新パッケージのダウンロードが完了しました。今すぐインストールしますか?",
"update.installLater": "後でインストール",
"update.installNow": "今すぐインストール",
"update.later": "後でリマインド",
"update.newVersion": "新しいバージョンが見つかりました",
"update.newVersionAvailable": "新しいバージョンが見つかりました: {{version}}",
"update.skipThisVersion": "このバージョンをスキップ"
}
+52 -70
View File
@@ -1,71 +1,53 @@
{
"common": {
"checkUpdates": "更新を確認しています..."
},
"dev": {
"devPanel": "開発者パネル",
"devTools": "開発者ツール",
"forceReload": "強制再読み込み",
"openStore": "ストレージファイルを開く",
"refreshMenu": "メニューを更新",
"reload": "再読み込み",
"title": "開発"
},
"edit": {
"copy": "コピー",
"cut": "切り取り",
"delete": "削除",
"paste": "貼り付け",
"redo": "やり直し",
"selectAll": "すべて選択",
"speech": "音声",
"startSpeaking": "読み上げ開始",
"stopSpeaking": "読み上げ停止",
"title": "編集",
"undo": "元に戻す"
},
"file": {
"preferences": "設定",
"quit": "終了",
"title": "ファイル"
},
"help": {
"about": "について",
"githubRepo": "GitHub リポジトリ",
"reportIssue": "問題を報告",
"title": "ヘルプ",
"visitWebsite": "公式ウェブサイトを訪問"
},
"macOS": {
"about": "{{appName}} について",
"devTools": "LobeHub 開発者ツール",
"hide": "{{appName}} を隠す",
"hideOthers": "他を隠す",
"preferences": "環境設定...",
"services": "サービス",
"unhide": "すべて表示"
},
"tray": {
"open": "{{appName}} を開く",
"quit": "終了",
"show": "{{appName}} を表示"
},
"view": {
"forceReload": "強制再読み込み",
"reload": "再読み込み",
"resetZoom": "ズームをリセット",
"title": "ビュー",
"toggleFullscreen": "フルスクリーン切替",
"zoomIn": "ズームイン",
"zoomOut": "ズームアウト"
},
"window": {
"bringAllToFront": "すべてのウィンドウを前面に",
"close": "閉じる",
"front": "すべてのウィンドウを前面に",
"minimize": "最小化",
"title": "ウィンドウ",
"toggleFullscreen": "フルスクリーン切替",
"zoom": "ズーム"
}
}
"common.checkUpdates": "更新を確認しています...",
"dev.devPanel": "開発者パネル",
"dev.devTools": "開発者ツール",
"dev.forceReload": "強制再読み込み",
"dev.openStore": "ストレージファイルを開く",
"dev.refreshMenu": "メニューを更新",
"dev.reload": "再読み込み",
"dev.title": "開発",
"edit.copy": "コピー",
"edit.cut": "切り取り",
"edit.delete": "削除",
"edit.paste": "貼り付け",
"edit.redo": "やり直し",
"edit.selectAll": "すべて選択",
"edit.speech": "音声",
"edit.startSpeaking": "読み上げ開始",
"edit.stopSpeaking": "読み上げ停止",
"edit.title": "編集",
"edit.undo": "元に戻す",
"file.preferences": "設定",
"file.quit": "終了",
"file.title": "ファイル",
"help.about": "について",
"help.githubRepo": "GitHub リポジトリ",
"help.reportIssue": "問題を報告",
"help.title": "ヘルプ",
"help.visitWebsite": "公式ウェブサイトを訪問",
"macOS.about": "{{appName}} について",
"macOS.devTools": "LobeHub 開発者ツール",
"macOS.hide": "{{appName}} を隠す",
"macOS.hideOthers": "他を隠す",
"macOS.preferences": "環境設定...",
"macOS.services": "サービス",
"macOS.unhide": "すべて表示",
"tray.open": "{{appName}} を開く",
"tray.quit": "終了",
"tray.show": "{{appName}} を表示",
"view.forceReload": "強制再読み込み",
"view.reload": "再読み込み",
"view.resetZoom": "ズームをリセット",
"view.title": "ビュー",
"view.toggleFullscreen": "フルスクリーン切替",
"view.zoomIn": "ズームイン",
"view.zoomOut": "ズームアウト",
"window.bringAllToFront": "すべてのウィンドウを前面に",
"window.close": "閉じる",
"window.front": "すべてのウィンドウを前面に",
"window.minimize": "最小化",
"window.title": "ウィンドウ",
"window.toggleFullscreen": "フルスクリーン切替",
"window.zoom": "ズーム"
}
@@ -1,32 +1,26 @@
{
"actions": {
"add": "추가",
"back": "뒤로",
"cancel": "취소",
"close": "닫기",
"confirm": "확인",
"delete": "삭제",
"edit": "편집",
"more": "더보기",
"next": "다음",
"ok": "확인",
"previous": "이전",
"refresh": "새로 고침",
"remove": "제거",
"retry": "다시 시도",
"save": "저장",
"search": "검색",
"submit": "제출"
},
"app": {
"description": "당신의 AI 비서 협업 플랫폼",
"name": "LobeHub"
},
"status": {
"error": "오류",
"info": "정보",
"loading": "로딩 중",
"success": "성공",
"warning": "경고"
}
}
"actions.add": "추가",
"actions.back": "뒤로",
"actions.cancel": "취소",
"actions.close": "닫기",
"actions.confirm": "확인",
"actions.delete": "삭제",
"actions.edit": "편집",
"actions.more": "더보기",
"actions.next": "다음",
"actions.ok": "확인",
"actions.previous": "이전",
"actions.refresh": "새로 고침",
"actions.remove": "제거",
"actions.retry": "다시 시도",
"actions.save": "저장",
"actions.search": "검색",
"actions.submit": "제출",
"app.description": "당신의 AI 비서 협업 플랫폼",
"app.name": "LobeHub",
"status.error": "오류",
"status.info": "정보",
"status.loading": "로딩 중",
"status.success": "성공",
"status.warning": "경고"
}
@@ -1,31 +1,23 @@
{
"about": {
"button": "확인",
"detail": "대형 언어 모델 기반의 채팅 애플리케이션",
"message": "{{appName}} {{appVersion}}",
"title": "정보"
},
"confirm": {
"cancel": "취소",
"no": "아니요",
"title": "확인",
"yes": "예"
},
"error": {
"button": "확인",
"detail": "작업 중 오류가 발생했습니다. 나중에 다시 시도해 주세요.",
"message": "오류 발생",
"title": "오류"
},
"update": {
"downloadAndInstall": "다운로드 및 설치",
"downloadComplete": "다운로드 완료",
"downloadCompleteMessage": "업데이트 패키지가 다운로드 완료되었습니다. 지금 설치하시겠습니까?",
"installLater": "나중에 설치",
"installNow": "지금 설치",
"later": "나중에 알림",
"newVersion": "새 버전 발견",
"newVersionAvailable": "새 버전 발견: {{version}}",
"skipThisVersion": "이 버전 건너뛰기"
}
}
"about.button": "확인",
"about.detail": "대형 언어 모델 기반의 채팅 애플리케이션",
"about.message": "{{appName}} {{appVersion}}",
"about.title": "정보",
"confirm.cancel": "취소",
"confirm.no": "아니요",
"confirm.title": "확인",
"confirm.yes": "",
"error.button": "확인",
"error.detail": "작업 중 오류가 발생했습니다. 나중에 다시 시도해 주세요.",
"error.message": "오류 발생",
"error.title": "오류",
"update.downloadAndInstall": "다운로드 및 설치",
"update.downloadComplete": "다운로드 완료",
"update.downloadCompleteMessage": "업데이트 패키지가 다운로드 완료되었습니다. 지금 설치하시겠습니까?",
"update.installLater": "나중에 설치",
"update.installNow": "지금 설치",
"update.later": "나중에 알림",
"update.newVersion": "새 버전 발견",
"update.newVersionAvailable": "새 버전 발견: {{version}}",
"update.skipThisVersion": "이 버전 건너뛰기"
}
+52 -70
View File
@@ -1,71 +1,53 @@
{
"common": {
"checkUpdates": "업데이트 확인 중..."
},
"dev": {
"devPanel": "개발자 패널",
"devTools": "개발자 도구",
"forceReload": "강제 새로 고침",
"openStore": "저장 파일 열기",
"refreshMenu": "메뉴 새로 고침",
"reload": "새로 고침",
"title": "개발"
},
"edit": {
"copy": "복사",
"cut": "잘라내기",
"delete": "삭제",
"paste": "붙여넣기",
"redo": "다시 실행",
"selectAll": "모두 선택",
"speech": "음성",
"startSpeaking": "읽기 시작",
"stopSpeaking": "읽기 중지",
"title": "편집",
"undo": "실행 취소"
},
"file": {
"preferences": "환경 설정",
"quit": "종료",
"title": "파일"
},
"help": {
"about": "정보",
"githubRepo": "GitHub 저장소",
"reportIssue": "문제 보고",
"title": "도움말",
"visitWebsite": "웹사이트 방문"
},
"macOS": {
"about": "{{appName}} 정보",
"devTools": "LobeHub 개발자 도구",
"hide": "{{appName}} 숨기기",
"hideOthers": "다른 것 숨기기",
"preferences": "환경 설정...",
"services": "서비스",
"unhide": "모두 표시"
},
"tray": {
"open": "{{appName}} 열기",
"quit": "종료",
"show": "{{appName}} 표시"
},
"view": {
"forceReload": "강제 새로 고침",
"reload": "새로 고침",
"resetZoom": "줌 초기화",
"title": "보기",
"toggleFullscreen": "전체 화면 전환",
"zoomIn": "확대",
"zoomOut": "축소"
},
"window": {
"bringAllToFront": "모든 창 앞으로 가져오기",
"close": "닫기",
"front": "모든 창 앞으로 가져오기",
"minimize": "최소화",
"title": "창",
"toggleFullscreen": "전체 화면 전환",
"zoom": "줌"
}
}
"common.checkUpdates": "업데이트 확인 중...",
"dev.devPanel": "개발자 패널",
"dev.devTools": "개발자 도구",
"dev.forceReload": "강제 새로 고침",
"dev.openStore": "저장 파일 열기",
"dev.refreshMenu": "메뉴 새로 고침",
"dev.reload": "새로 고침",
"dev.title": "개발",
"edit.copy": "복사",
"edit.cut": "잘라내기",
"edit.delete": "삭제",
"edit.paste": "붙여넣기",
"edit.redo": "다시 실행",
"edit.selectAll": "모두 선택",
"edit.speech": "음성",
"edit.startSpeaking": "읽기 시작",
"edit.stopSpeaking": "읽기 중지",
"edit.title": "편집",
"edit.undo": "실행 취소",
"file.preferences": "환경 설정",
"file.quit": "종료",
"file.title": "파일",
"help.about": "정보",
"help.githubRepo": "GitHub 저장소",
"help.reportIssue": "문제 보고",
"help.title": "도움말",
"help.visitWebsite": "웹사이트 방문",
"macOS.about": "{{appName}} 정보",
"macOS.devTools": "LobeHub 개발자 도구",
"macOS.hide": "{{appName}} 숨기기",
"macOS.hideOthers": "다른 것 숨기기",
"macOS.preferences": "환경 설정...",
"macOS.services": "서비스",
"macOS.unhide": "모두 표시",
"tray.open": "{{appName}} 열기",
"tray.quit": "종료",
"tray.show": "{{appName}} 표시",
"view.forceReload": "강제 새로 고침",
"view.reload": "새로 고침",
"view.resetZoom": "줌 초기화",
"view.title": "보기",
"view.toggleFullscreen": "전체 화면 전환",
"view.zoomIn": "확대",
"view.zoomOut": "축소",
"window.bringAllToFront": "모든 창 앞으로 가져오기",
"window.close": "닫기",
"window.front": "모든 창 앞으로 가져오기",
"window.minimize": "최소화",
"window.title": "",
"window.toggleFullscreen": "전체 화면 전환",
"window.zoom": "줌"
}
@@ -1,32 +1,26 @@
{
"actions": {
"add": "Toevoegen",
"back": "Terug",
"cancel": "Annuleren",
"close": "Sluiten",
"confirm": "Bevestigen",
"delete": "Verwijderen",
"edit": "Bewerken",
"more": "Meer",
"next": "Volgende stap",
"ok": "OK",
"previous": "Vorige stap",
"refresh": "Vernieuwen",
"remove": "Verwijderen",
"retry": "Opnieuw proberen",
"save": "Opslaan",
"search": "Zoeken",
"submit": "Indienen"
},
"app": {
"description": "Jouw AI-assistent samenwerkingsplatform",
"name": "LobeHub"
},
"status": {
"error": "Fout",
"info": "Informatie",
"loading": "Laden",
"success": "Succes",
"warning": "Waarschuwing"
}
}
"actions.add": "Toevoegen",
"actions.back": "Terug",
"actions.cancel": "Annuleren",
"actions.close": "Sluiten",
"actions.confirm": "Bevestigen",
"actions.delete": "Verwijderen",
"actions.edit": "Bewerken",
"actions.more": "Meer",
"actions.next": "Volgende stap",
"actions.ok": "OK",
"actions.previous": "Vorige stap",
"actions.refresh": "Vernieuwen",
"actions.remove": "Verwijderen",
"actions.retry": "Opnieuw proberen",
"actions.save": "Opslaan",
"actions.search": "Zoeken",
"actions.submit": "Indienen",
"app.description": "Jouw AI-assistent samenwerkingsplatform",
"app.name": "LobeHub",
"status.error": "Fout",
"status.info": "Informatie",
"status.loading": "Laden",
"status.success": "Succes",
"status.warning": "Waarschuwing"
}
@@ -1,31 +1,23 @@
{
"about": {
"button": "Bevestigen",
"detail": "Een chatapplicatie gebaseerd op een groot taalmodel",
"message": "{{appName}} {{appVersion}}",
"title": "Over"
},
"confirm": {
"cancel": "Annuleren",
"no": "Nee",
"title": "Bevestigen",
"yes": "Ja"
},
"error": {
"button": "Bevestigen",
"detail": "Er is een fout opgetreden tijdens de operatie, probeer het later opnieuw",
"message": "Er is een fout opgetreden",
"title": "Fout"
},
"update": {
"downloadAndInstall": "Downloaden en installeren",
"downloadComplete": "Download voltooid",
"downloadCompleteMessage": "Het updatepakket is gedownload, wilt u het nu installeren?",
"installLater": "Later installeren",
"installNow": "Nu installeren",
"later": "Later herinneren",
"newVersion": "Nieuwe versie gevonden",
"newVersionAvailable": "Nieuwe versie beschikbaar: {{version}}",
"skipThisVersion": "Deze versie overslaan"
}
}
"about.button": "Bevestigen",
"about.detail": "Een chatapplicatie gebaseerd op een groot taalmodel",
"about.message": "{{appName}} {{appVersion}}",
"about.title": "Over",
"confirm.cancel": "Annuleren",
"confirm.no": "Nee",
"confirm.title": "Bevestigen",
"confirm.yes": "Ja",
"error.button": "Bevestigen",
"error.detail": "Er is een fout opgetreden tijdens de operatie, probeer het later opnieuw",
"error.message": "Er is een fout opgetreden",
"error.title": "Fout",
"update.downloadAndInstall": "Downloaden en installeren",
"update.downloadComplete": "Download voltooid",
"update.downloadCompleteMessage": "Het updatepakket is gedownload, wilt u het nu installeren?",
"update.installLater": "Later installeren",
"update.installNow": "Nu installeren",
"update.later": "Later herinneren",
"update.newVersion": "Nieuwe versie gevonden",
"update.newVersionAvailable": "Nieuwe versie beschikbaar: {{version}}",
"update.skipThisVersion": "Deze versie overslaan"
}
+52 -70
View File
@@ -1,71 +1,53 @@
{
"common": {
"checkUpdates": "Updates controleren..."
},
"dev": {
"devPanel": "Ontwikkelaarspaneel",
"devTools": "Ontwikkelaarstools",
"forceReload": "Forceer herladen",
"openStore": "Open opslagbestand",
"refreshMenu": "Menu verversen",
"reload": "Herladen",
"title": "Ontwikkeling"
},
"edit": {
"copy": "Kopiëren",
"cut": "Knippen",
"delete": "Verwijderen",
"paste": "Plakken",
"redo": "Opnieuw doen",
"selectAll": "Alles selecteren",
"speech": "Spraak",
"startSpeaking": "Begin met voorlezen",
"stopSpeaking": "Stop met voorlezen",
"title": "Bewerken",
"undo": "Ongedaan maken"
},
"file": {
"preferences": "Voorkeuren",
"quit": "Afsluiten",
"title": "Bestand"
},
"help": {
"about": "Over",
"githubRepo": "GitHub-repo",
"reportIssue": "Probleem melden",
"title": "Hulp",
"visitWebsite": "Bezoek de website"
},
"macOS": {
"about": "Over {{appName}}",
"devTools": "LobeHub Ontwikkelaarstools",
"hide": "Verberg {{appName}}",
"hideOthers": "Verberg anderen",
"preferences": "Voorkeuren...",
"services": "Diensten",
"unhide": "Toon alles"
},
"tray": {
"open": "Open {{appName}}",
"quit": "Afsluiten",
"show": "Toon {{appName}}"
},
"view": {
"forceReload": "Forceer herladen",
"reload": "Herladen",
"resetZoom": "Zoom resetten",
"title": "Weergave",
"toggleFullscreen": "Schakel volledig scherm in/uit",
"zoomIn": "Inzoomen",
"zoomOut": "Uitzoomen"
},
"window": {
"bringAllToFront": "Breng alle vensters naar voren",
"close": "Sluiten",
"front": "Breng alle vensters naar voren",
"minimize": "Minimaliseren",
"title": "Venster",
"toggleFullscreen": "Schakel volledig scherm in/uit",
"zoom": "Inzoomen"
}
}
"common.checkUpdates": "Updates controleren...",
"dev.devPanel": "Ontwikkelaarspaneel",
"dev.devTools": "Ontwikkelaarstools",
"dev.forceReload": "Forceer herladen",
"dev.openStore": "Open opslagbestand",
"dev.refreshMenu": "Menu verversen",
"dev.reload": "Herladen",
"dev.title": "Ontwikkeling",
"edit.copy": "Kopiëren",
"edit.cut": "Knippen",
"edit.delete": "Verwijderen",
"edit.paste": "Plakken",
"edit.redo": "Opnieuw doen",
"edit.selectAll": "Alles selecteren",
"edit.speech": "Spraak",
"edit.startSpeaking": "Begin met voorlezen",
"edit.stopSpeaking": "Stop met voorlezen",
"edit.title": "Bewerken",
"edit.undo": "Ongedaan maken",
"file.preferences": "Voorkeuren",
"file.quit": "Afsluiten",
"file.title": "Bestand",
"help.about": "Over",
"help.githubRepo": "GitHub-repo",
"help.reportIssue": "Probleem melden",
"help.title": "Hulp",
"help.visitWebsite": "Bezoek de website",
"macOS.about": "Over {{appName}}",
"macOS.devTools": "LobeHub Ontwikkelaarstools",
"macOS.hide": "Verberg {{appName}}",
"macOS.hideOthers": "Verberg anderen",
"macOS.preferences": "Voorkeuren...",
"macOS.services": "Diensten",
"macOS.unhide": "Toon alles",
"tray.open": "Open {{appName}}",
"tray.quit": "Afsluiten",
"tray.show": "Toon {{appName}}",
"view.forceReload": "Forceer herladen",
"view.reload": "Herladen",
"view.resetZoom": "Zoom resetten",
"view.title": "Weergave",
"view.toggleFullscreen": "Schakel volledig scherm in/uit",
"view.zoomIn": "Inzoomen",
"view.zoomOut": "Uitzoomen",
"window.bringAllToFront": "Breng alle vensters naar voren",
"window.close": "Sluiten",
"window.front": "Breng alle vensters naar voren",
"window.minimize": "Minimaliseren",
"window.title": "Venster",
"window.toggleFullscreen": "Schakel volledig scherm in/uit",
"window.zoom": "Inzoomen"
}
@@ -1,32 +1,26 @@
{
"actions": {
"add": "Dodaj",
"back": "Wstecz",
"cancel": "Anuluj",
"close": "Zamknij",
"confirm": "Potwierdź",
"delete": "Usuń",
"edit": "Edytuj",
"more": "Więcej",
"next": "Dalej",
"ok": "OK",
"previous": "Cofnij",
"refresh": "Odśwież",
"remove": "Usuń",
"retry": "Spróbuj ponownie",
"save": "Zapisz",
"search": "Szukaj",
"submit": "Wyślij"
},
"app": {
"description": "Twoja platforma współpracy z asystentem AI",
"name": "LobeHub"
},
"status": {
"error": "Błąd",
"info": "Informacja",
"loading": "Ładowanie",
"success": "Sukces",
"warning": "Ostrzeżenie"
}
}
"actions.add": "Dodaj",
"actions.back": "Wstecz",
"actions.cancel": "Anuluj",
"actions.close": "Zamknij",
"actions.confirm": "Potwierdź",
"actions.delete": "Usuń",
"actions.edit": "Edytuj",
"actions.more": "Więcej",
"actions.next": "Dalej",
"actions.ok": "OK",
"actions.previous": "Cofnij",
"actions.refresh": "Odśwież",
"actions.remove": "Usuń",
"actions.retry": "Spróbuj ponownie",
"actions.save": "Zapisz",
"actions.search": "Szukaj",
"actions.submit": "Wyślij",
"app.description": "Twoja platforma współpracy z asystentem AI",
"app.name": "LobeHub",
"status.error": "Błąd",
"status.info": "Informacja",
"status.loading": "Ładowanie",
"status.success": "Sukces",
"status.warning": "Ostrzeżenie"
}
@@ -1,31 +1,23 @@
{
"about": {
"button": "OK",
"detail": "Aplikacja czatu oparta na dużym modelu językowym",
"message": "{{appName}} {{appVersion}}",
"title": "O aplikacji"
},
"confirm": {
"cancel": "Anuluj",
"no": "Nie",
"title": "Potwierdzenie",
"yes": "Tak"
},
"error": {
"button": "OK",
"detail": "Wystąpił błąd podczas operacji, spróbuj ponownie później",
"message": "Wystąpił błąd",
"title": "Błąd"
},
"update": {
"downloadAndInstall": "Pobierz i zainstaluj",
"downloadComplete": "Pobieranie zakończone",
"downloadCompleteMessage": "Pakiet aktualizacji został pobrany, czy chcesz go teraz zainstalować?",
"installLater": "Zainstaluj później",
"installNow": "Zainstaluj teraz",
"later": "Przypomnij później",
"newVersion": "Nowa wersja dostępna",
"newVersionAvailable": "Znaleziono nową wersję: {{version}}",
"skipThisVersion": "Pomiń tę wersję"
}
}
"about.button": "OK",
"about.detail": "Aplikacja czatu oparta na dużym modelu językowym",
"about.message": "{{appName}} {{appVersion}}",
"about.title": "O aplikacji",
"confirm.cancel": "Anuluj",
"confirm.no": "Nie",
"confirm.title": "Potwierdzenie",
"confirm.yes": "Tak",
"error.button": "OK",
"error.detail": "Wystąpił błąd podczas operacji, spróbuj ponownie później",
"error.message": "Wystąpił błąd",
"error.title": "Błąd",
"update.downloadAndInstall": "Pobierz i zainstaluj",
"update.downloadComplete": "Pobieranie zakończone",
"update.downloadCompleteMessage": "Pakiet aktualizacji został pobrany, czy chcesz go teraz zainstalować?",
"update.installLater": "Zainstaluj później",
"update.installNow": "Zainstaluj teraz",
"update.later": "Przypomnij później",
"update.newVersion": "Nowa wersja dostępna",
"update.newVersionAvailable": "Znaleziono nową wersję: {{version}}",
"update.skipThisVersion": "Pomiń tę wersję"
}
+52 -70
View File
@@ -1,71 +1,53 @@
{
"common": {
"checkUpdates": "Sprawdzanie aktualizacji..."
},
"dev": {
"devPanel": "Panel dewelopera",
"devTools": "Narzędzia dewelopera",
"forceReload": "Wymuś ponowne załadowanie",
"openStore": "Otwórz plik magazynu",
"refreshMenu": "Odśwież menu",
"reload": "Przeładuj",
"title": "Rozwój"
},
"edit": {
"copy": "Kopiuj",
"cut": "Wytnij",
"delete": "Usuń",
"paste": "Wklej",
"redo": "Ponów",
"selectAll": "Zaznacz wszystko",
"speech": "Mowa",
"startSpeaking": "Rozpocznij czytanie",
"stopSpeaking": "Zatrzymaj czytanie",
"title": "Edycja",
"undo": "Cofnij"
},
"file": {
"preferences": "Preferencje",
"quit": "Zakończ",
"title": "Plik"
},
"help": {
"about": "O",
"githubRepo": "Repozytorium GitHub",
"reportIssue": "Zgłoś problem",
"title": "Pomoc",
"visitWebsite": "Odwiedź stronę internetową"
},
"macOS": {
"about": "O {{appName}}",
"devTools": "Narzędzia dewelopera LobeHub",
"hide": "Ukryj {{appName}}",
"hideOthers": "Ukryj inne",
"preferences": "Ustawienia...",
"services": "Usługi",
"unhide": "Pokaż wszystko"
},
"tray": {
"open": "Otwórz {{appName}}",
"quit": "Zakończ",
"show": "Pokaż {{appName}}"
},
"view": {
"forceReload": "Wymuś ponowne załadowanie",
"reload": "Przeładuj",
"resetZoom": "Zresetuj powiększenie",
"title": "Widok",
"toggleFullscreen": "Przełącz tryb pełnoekranowy",
"zoomIn": "Powiększ",
"zoomOut": "Pomniejsz"
},
"window": {
"bringAllToFront": "Przenieś wszystkie okna na wierzch",
"close": "Zamknij",
"front": "Przenieś wszystkie okna na wierzch",
"minimize": "Zminimalizuj",
"title": "Okno",
"toggleFullscreen": "Przełącz tryb pełnoekranowy",
"zoom": "Powiększenie"
}
}
"common.checkUpdates": "Sprawdzanie aktualizacji...",
"dev.devPanel": "Panel dewelopera",
"dev.devTools": "Narzędzia dewelopera",
"dev.forceReload": "Wymuś ponowne załadowanie",
"dev.openStore": "Otwórz plik magazynu",
"dev.refreshMenu": "Odśwież menu",
"dev.reload": "Przeładuj",
"dev.title": "Rozwój",
"edit.copy": "Kopiuj",
"edit.cut": "Wytnij",
"edit.delete": "Usuń",
"edit.paste": "Wklej",
"edit.redo": "Ponów",
"edit.selectAll": "Zaznacz wszystko",
"edit.speech": "Mowa",
"edit.startSpeaking": "Rozpocznij czytanie",
"edit.stopSpeaking": "Zatrzymaj czytanie",
"edit.title": "Edycja",
"edit.undo": "Cofnij",
"file.preferences": "Preferencje",
"file.quit": "Zakończ",
"file.title": "Plik",
"help.about": "O",
"help.githubRepo": "Repozytorium GitHub",
"help.reportIssue": "Zgłoś problem",
"help.title": "Pomoc",
"help.visitWebsite": "Odwiedź stronę internetową",
"macOS.about": "O {{appName}}",
"macOS.devTools": "Narzędzia dewelopera LobeHub",
"macOS.hide": "Ukryj {{appName}}",
"macOS.hideOthers": "Ukryj inne",
"macOS.preferences": "Ustawienia...",
"macOS.services": "Usługi",
"macOS.unhide": "Pokaż wszystko",
"tray.open": "Otwórz {{appName}}",
"tray.quit": "Zakończ",
"tray.show": "Pokaż {{appName}}",
"view.forceReload": "Wymuś ponowne załadowanie",
"view.reload": "Przeładuj",
"view.resetZoom": "Zresetuj powiększenie",
"view.title": "Widok",
"view.toggleFullscreen": "Przełącz tryb pełnoekranowy",
"view.zoomIn": "Powiększ",
"view.zoomOut": "Pomniejsz",
"window.bringAllToFront": "Przenieś wszystkie okna na wierzch",
"window.close": "Zamknij",
"window.front": "Przenieś wszystkie okna na wierzch",
"window.minimize": "Zminimalizuj",
"window.title": "Okno",
"window.toggleFullscreen": "Przełącz tryb pełnoekranowy",
"window.zoom": "Powiększenie"
}
@@ -1,32 +1,26 @@
{
"actions": {
"add": "Adicionar",
"back": "Voltar",
"cancel": "Cancelar",
"close": "Fechar",
"confirm": "Confirmar",
"delete": "Excluir",
"edit": "Editar",
"more": "Mais",
"next": "Próximo",
"ok": "OK",
"previous": "Anterior",
"refresh": "Atualizar",
"remove": "Remover",
"retry": "Tentar novamente",
"save": "Salvar",
"search": "Pesquisar",
"submit": "Enviar"
},
"app": {
"description": "Sua plataforma de colaboração com assistente de IA",
"name": "LobeHub"
},
"status": {
"error": "Erro",
"info": "Informação",
"loading": "Carregando",
"success": "Sucesso",
"warning": "Aviso"
}
}
"actions.add": "Adicionar",
"actions.back": "Voltar",
"actions.cancel": "Cancelar",
"actions.close": "Fechar",
"actions.confirm": "Confirmar",
"actions.delete": "Excluir",
"actions.edit": "Editar",
"actions.more": "Mais",
"actions.next": "Próximo",
"actions.ok": "OK",
"actions.previous": "Anterior",
"actions.refresh": "Atualizar",
"actions.remove": "Remover",
"actions.retry": "Tentar novamente",
"actions.save": "Salvar",
"actions.search": "Pesquisar",
"actions.submit": "Enviar",
"app.description": "Sua plataforma de colaboração com assistente de IA",
"app.name": "LobeHub",
"status.error": "Erro",
"status.info": "Informação",
"status.loading": "Carregando",
"status.success": "Sucesso",
"status.warning": "Aviso"
}
@@ -1,31 +1,23 @@
{
"about": {
"button": "Confirmar",
"detail": "Um aplicativo de chat baseado em um grande modelo de linguagem",
"message": "{{appName}} {{appVersion}}",
"title": "Sobre"
},
"confirm": {
"cancel": "Cancelar",
"no": "Não",
"title": "Confirmar",
"yes": "Sim"
},
"error": {
"button": "Confirmar",
"detail": "Ocorreu um erro durante a operação, por favor tente novamente mais tarde",
"message": "Ocorreu um erro",
"title": "Erro"
},
"update": {
"downloadAndInstall": "Baixar e instalar",
"downloadComplete": "Download completo",
"downloadCompleteMessage": "O pacote de atualização foi baixado com sucesso, deseja instalá-lo agora?",
"installLater": "Instalar depois",
"installNow": "Instalar agora",
"later": "Lembrar mais tarde",
"newVersion": "Nova versão disponível",
"newVersionAvailable": "Nova versão encontrada: {{version}}",
"skipThisVersion": "Ignorar esta versão"
}
}
"about.button": "Confirmar",
"about.detail": "Um aplicativo de chat baseado em um grande modelo de linguagem",
"about.message": "{{appName}} {{appVersion}}",
"about.title": "Sobre",
"confirm.cancel": "Cancelar",
"confirm.no": "Não",
"confirm.title": "Confirmar",
"confirm.yes": "Sim",
"error.button": "Confirmar",
"error.detail": "Ocorreu um erro durante a operação, por favor tente novamente mais tarde",
"error.message": "Ocorreu um erro",
"error.title": "Erro",
"update.downloadAndInstall": "Baixar e instalar",
"update.downloadComplete": "Download completo",
"update.downloadCompleteMessage": "O pacote de atualização foi baixado com sucesso, deseja instalá-lo agora?",
"update.installLater": "Instalar depois",
"update.installNow": "Instalar agora",
"update.later": "Lembrar mais tarde",
"update.newVersion": "Nova versão disponível",
"update.newVersionAvailable": "Nova versão encontrada: {{version}}",
"update.skipThisVersion": "Ignorar esta versão"
}
+52 -70
View File
@@ -1,71 +1,53 @@
{
"common": {
"checkUpdates": "Verificando atualizações..."
},
"dev": {
"devPanel": "Painel do Desenvolvedor",
"devTools": "Ferramentas do Desenvolvedor",
"forceReload": "Recarregar Forçadamente",
"openStore": "Abrir arquivo de armazenamento",
"refreshMenu": "Atualizar menu",
"reload": "Recarregar",
"title": "Desenvolvimento"
},
"edit": {
"copy": "Copiar",
"cut": "Cortar",
"delete": "Excluir",
"paste": "Colar",
"redo": "Refazer",
"selectAll": "Selecionar Tudo",
"speech": "Fala",
"startSpeaking": "Começar a Ler",
"stopSpeaking": "Parar de Ler",
"title": "Edição",
"undo": "Desfazer"
},
"file": {
"preferences": "Preferências",
"quit": "Sair",
"title": "Arquivo"
},
"help": {
"about": "Sobre",
"githubRepo": "Repositório do GitHub",
"reportIssue": "Reportar Problema",
"title": "Ajuda",
"visitWebsite": "Visitar o Site"
},
"macOS": {
"about": "Sobre {{appName}}",
"devTools": "Ferramentas do Desenvolvedor LobeHub",
"hide": "Ocultar {{appName}}",
"hideOthers": "Ocultar Outros",
"preferences": "Configurações...",
"services": "Serviços",
"unhide": "Mostrar Todos"
},
"tray": {
"open": "Abrir {{appName}}",
"quit": "Sair",
"show": "Mostrar {{appName}}"
},
"view": {
"forceReload": "Recarregar Forçadamente",
"reload": "Recarregar",
"resetZoom": "Redefinir Zoom",
"title": "Visualização",
"toggleFullscreen": "Alternar Tela Cheia",
"zoomIn": "Aumentar",
"zoomOut": "Diminuir"
},
"window": {
"bringAllToFront": "Trazer Todas as Janelas para Frente",
"close": "Fechar",
"front": "Trazer Todas as Janelas para Frente",
"minimize": "Minimizar",
"title": "Janela",
"toggleFullscreen": "Alternar Tela Cheia",
"zoom": "Zoom"
}
}
"common.checkUpdates": "Verificando atualizações...",
"dev.devPanel": "Painel do Desenvolvedor",
"dev.devTools": "Ferramentas do Desenvolvedor",
"dev.forceReload": "Recarregar Forçadamente",
"dev.openStore": "Abrir arquivo de armazenamento",
"dev.refreshMenu": "Atualizar menu",
"dev.reload": "Recarregar",
"dev.title": "Desenvolvimento",
"edit.copy": "Copiar",
"edit.cut": "Cortar",
"edit.delete": "Excluir",
"edit.paste": "Colar",
"edit.redo": "Refazer",
"edit.selectAll": "Selecionar Tudo",
"edit.speech": "Fala",
"edit.startSpeaking": "Começar a Ler",
"edit.stopSpeaking": "Parar de Ler",
"edit.title": "Edição",
"edit.undo": "Desfazer",
"file.preferences": "Preferências",
"file.quit": "Sair",
"file.title": "Arquivo",
"help.about": "Sobre",
"help.githubRepo": "Repositório do GitHub",
"help.reportIssue": "Reportar Problema",
"help.title": "Ajuda",
"help.visitWebsite": "Visitar o Site",
"macOS.about": "Sobre {{appName}}",
"macOS.devTools": "Ferramentas do Desenvolvedor LobeHub",
"macOS.hide": "Ocultar {{appName}}",
"macOS.hideOthers": "Ocultar Outros",
"macOS.preferences": "Configurações...",
"macOS.services": "Serviços",
"macOS.unhide": "Mostrar Todos",
"tray.open": "Abrir {{appName}}",
"tray.quit": "Sair",
"tray.show": "Mostrar {{appName}}",
"view.forceReload": "Recarregar Forçadamente",
"view.reload": "Recarregar",
"view.resetZoom": "Redefinir Zoom",
"view.title": "Visualização",
"view.toggleFullscreen": "Alternar Tela Cheia",
"view.zoomIn": "Aumentar",
"view.zoomOut": "Diminuir",
"window.bringAllToFront": "Trazer Todas as Janelas para Frente",
"window.close": "Fechar",
"window.front": "Trazer Todas as Janelas para Frente",
"window.minimize": "Minimizar",
"window.title": "Janela",
"window.toggleFullscreen": "Alternar Tela Cheia",
"window.zoom": "Zoom"
}
@@ -1,32 +1,26 @@
{
"actions": {
"add": "Добавить",
"back": "Назад",
"cancel": "Отмена",
"close": "Закрыть",
"confirm": "Подтвердить",
"delete": "Удалить",
"edit": "Редактировать",
"more": "Больше",
"next": "Далее",
"ok": "ОК",
"previous": "Назад",
"refresh": "Обновить",
"remove": "Удалить",
"retry": "Повторить",
"save": "Сохранить",
"search": "Поиск",
"submit": "Отправить"
},
"app": {
"description": "Ваша платформа для совместной работы с ИИ",
"name": "LobeHub"
},
"status": {
"error": "Ошибка",
"info": "Информация",
"loading": "Загрузка",
"success": "Успех",
"warning": "Предупреждение"
}
}
"actions.add": "Добавить",
"actions.back": "Назад",
"actions.cancel": "Отмена",
"actions.close": "Закрыть",
"actions.confirm": "Подтвердить",
"actions.delete": "Удалить",
"actions.edit": "Редактировать",
"actions.more": "Больше",
"actions.next": "Далее",
"actions.ok": "ОК",
"actions.previous": "Назад",
"actions.refresh": "Обновить",
"actions.remove": "Удалить",
"actions.retry": "Повторить",
"actions.save": "Сохранить",
"actions.search": "Поиск",
"actions.submit": "Отправить",
"app.description": "Ваша платформа для совместной работы с ИИ",
"app.name": "LobeHub",
"status.error": "Ошибка",
"status.info": "Информация",
"status.loading": "Загрузка",
"status.success": "Успех",
"status.warning": "Предупреждение"
}
@@ -1,31 +1,23 @@
{
"about": {
"button": "Подтвердить",
"detail": "Приложение для чата на основе большой языковой модели",
"message": "{{appName}} {{appVersion}}",
"title": "О приложении"
},
"confirm": {
"cancel": "Отмена",
"no": "Нет",
"title": "Подтверждение",
"yes": "Да"
},
"error": {
"button": "Подтвердить",
"detail": "Произошла ошибка во время операции, пожалуйста, попробуйте позже",
"message": "Произошла ошибка",
"title": "Ошибка"
},
"update": {
"downloadAndInstall": "Скачать и установить",
"downloadComplete": "Скачивание завершено",
"downloadCompleteMessage": "Обновление загружено, хотите установить сейчас?",
"installLater": "Установить позже",
"installNow": "Установить сейчас",
"later": "Напомнить позже",
"newVersion": "Обнаружена новая версия",
"newVersionAvailable": "Обнаружена новая версия: {{version}}",
"skipThisVersion": "Пропустить эту версию"
}
}
"about.button": "Подтвердить",
"about.detail": "Приложение для чата на основе большой языковой модели",
"about.message": "{{appName}} {{appVersion}}",
"about.title": "О приложении",
"confirm.cancel": "Отмена",
"confirm.no": "Нет",
"confirm.title": "Подтверждение",
"confirm.yes": "Да",
"error.button": "Подтвердить",
"error.detail": "Произошла ошибка во время операции, пожалуйста, попробуйте позже",
"error.message": "Произошла ошибка",
"error.title": "Ошибка",
"update.downloadAndInstall": "Скачать и установить",
"update.downloadComplete": "Скачивание завершено",
"update.downloadCompleteMessage": "Обновление загружено, хотите установить сейчас?",
"update.installLater": "Установить позже",
"update.installNow": "Установить сейчас",
"update.later": "Напомнить позже",
"update.newVersion": "Обнаружена новая версия",
"update.newVersionAvailable": "Обнаружена новая версия: {{version}}",
"update.skipThisVersion": "Пропустить эту версию"
}
+52 -70
View File
@@ -1,71 +1,53 @@
{
"common": {
"checkUpdates": "Проверка обновлений..."
},
"dev": {
"devPanel": "Панель разработчика",
"devTools": "Инструменты разработчика",
"forceReload": ринудительная перезагрузка",
"openStore": "Открыть файл хранилища",
"refreshMenu": "Обновить меню",
"reload": "Перезагрузить",
"title": "Разработка"
},
"edit": {
"copy": "Копировать",
"cut": "Вырезать",
"delete": "Удалить",
"paste": "Вставить",
"redo": "Повторить",
"selectAll": "Выбрать все",
"speech": "Речь",
"startSpeaking": "Начать чтение",
"stopSpeaking": "Остановить чтение",
"title": "Редактирование",
"undo": "Отменить"
},
"file": {
"preferences": "Настройки",
"quit": "Выйти",
"title": "Файл"
},
"help": {
"about": "О программе",
"githubRepo": "Репозиторий GitHub",
"reportIssue": "Сообщить о проблеме",
"title": "Помощь",
"visitWebsite": "Посетить сайт"
},
"macOS": {
"about": "О {{appName}}",
"devTools": "Инструменты разработчика LobeHub",
"hide": "Скрыть {{appName}}",
"hideOthers": "Скрыть другие",
"preferences": "Настройки...",
"services": "Сервисы",
"unhide": "Показать все"
},
"tray": {
"open": "Открыть {{appName}}",
"quit": "Выйти",
"show": "Показать {{appName}}"
},
"view": {
"forceReload": "Принудительная перезагрузка",
"reload": "Перезагрузить",
"resetZoom": "Сбросить масштаб",
"title": "Вид",
"toggleFullscreen": "Переключить полноэкранный режим",
"zoomIn": "Увеличить",
"zoomOut": "Уменьшить"
},
"window": {
"bringAllToFront": "Вывести все окна на передний план",
"close": "Закрыть",
"front": "Вывести все окна на передний план",
"minimize": "Свернуть",
"title": "Окно",
"toggleFullscreen": "Переключить полноэкранный режим",
"zoom": "Масштаб"
}
}
"common.checkUpdates": "Проверка обновлений...",
"dev.devPanel": "Панель разработчика",
"dev.devTools": "Инструменты разработчика",
"dev.forceReload": "Принудительная перезагрузка",
"dev.openStore": "Открыть файл хранилища",
"dev.refreshMenu": "Обновить меню",
"dev.reload": "Перезагрузить",
"dev.title": "Разработка",
"edit.copy": "Копировать",
"edit.cut": "Вырезать",
"edit.delete": "Удалить",
"edit.paste": "Вставить",
"edit.redo": "Повторить",
"edit.selectAll": "Выбрать все",
"edit.speech": "Речь",
"edit.startSpeaking": "Начать чтение",
"edit.stopSpeaking": "Остановить чтение",
"edit.title": "Редактирование",
"edit.undo": "Отменить",
"file.preferences": "Настройки",
"file.quit": "Выйти",
"file.title": "Файл",
"help.about": "О программе",
"help.githubRepo": "Репозиторий GitHub",
"help.reportIssue": "Сообщить о проблеме",
"help.title": "Помощь",
"help.visitWebsite": "Посетить сайт",
"macOS.about": "О {{appName}}",
"macOS.devTools": "Инструменты разработчика LobeHub",
"macOS.hide": "Скрыть {{appName}}",
"macOS.hideOthers": "Скрыть другие",
"macOS.preferences": "Настройки...",
"macOS.services": "Сервисы",
"macOS.unhide": "Показать все",
"tray.open": "Открыть {{appName}}",
"tray.quit": "Выйти",
"tray.show": "Показать {{appName}}",
"view.forceReload": "Принудительная перезагрузка",
"view.reload": "Перезагрузить",
"view.resetZoom": "Сбросить масштаб",
"view.title": "Вид",
"view.toggleFullscreen": "Переключить полноэкранный режим",
"view.zoomIn": "Увеличить",
"view.zoomOut": "Уменьшить",
"window.bringAllToFront": "Вывести все окна на передний план",
"window.close": "Закрыть",
"window.front": "Вывести все окна на передний план",
"window.minimize": "Свернуть",
"window.title": "Окно",
"window.toggleFullscreen": "Переключить полноэкранный режим",
"window.zoom": "Масштаб"
}
@@ -1,32 +1,26 @@
{
"actions": {
"add": "Ekle",
"back": "Geri",
"cancel": "İptal",
"close": "Kapat",
"confirm": "Onayla",
"delete": "Sil",
"edit": "Düzenle",
"more": "Daha Fazla",
"next": "Sonraki",
"ok": "Tamam",
"previous": "Önceki",
"refresh": "Yenile",
"remove": "Kaldır",
"retry": "Yeniden Dene",
"save": "Kaydet",
"search": "Ara",
"submit": "Gönder"
},
"app": {
"description": "AI asistanınız için işbirliği platformu",
"name": "LobeHub"
},
"status": {
"error": "Hata",
"info": "Bilgi",
"loading": "Yükleniyor",
"success": "Başarılı",
"warning": "Uyarı"
}
}
"actions.add": "Ekle",
"actions.back": "Geri",
"actions.cancel": "İptal",
"actions.close": "Kapat",
"actions.confirm": "Onayla",
"actions.delete": "Sil",
"actions.edit": "Düzenle",
"actions.more": "Daha Fazla",
"actions.next": "Sonraki",
"actions.ok": "Tamam",
"actions.previous": "Önceki",
"actions.refresh": "Yenile",
"actions.remove": "Kaldır",
"actions.retry": "Yeniden Dene",
"actions.save": "Kaydet",
"actions.search": "Ara",
"actions.submit": "Gönder",
"app.description": "AI asistanınız için işbirliği platformu",
"app.name": "LobeHub",
"status.error": "Hata",
"status.info": "Bilgi",
"status.loading": "Yükleniyor",
"status.success": "Başarılı",
"status.warning": "Uyarı"
}
@@ -1,31 +1,23 @@
{
"about": {
"button": "Tamam",
"detail": "Büyük dil modeli tabanlı bir sohbet uygulaması",
"message": "{{appName}} {{appVersion}}",
"title": "Hakkında"
},
"confirm": {
"cancel": "İptal",
"no": "Hayır",
"title": "Onay",
"yes": "Evet"
},
"error": {
"button": "Tamam",
"detail": "İşlem sırasında bir hata oluştu, lütfen daha sonra tekrar deneyin",
"message": "Hata oluştu",
"title": "Hata"
},
"update": {
"downloadAndInstall": "İndir ve Yükle",
"downloadComplete": "İndirme tamamlandı",
"downloadCompleteMessage": "Güncelleme paketi indirildi, hemen yüklemek ister misiniz?",
"installLater": "Sonra yükle",
"installNow": "Şimdi yükle",
"later": "Sonra hatırlat",
"newVersion": "Yeni sürüm bulundu",
"newVersionAvailable": "Yeni sürüm bulundu: {{version}}",
"skipThisVersion": "Bu sürümü atla"
}
}
"about.button": "Tamam",
"about.detail": "Büyük dil modeli tabanlı bir sohbet uygulaması",
"about.message": "{{appName}} {{appVersion}}",
"about.title": "Hakkında",
"confirm.cancel": "İptal",
"confirm.no": "Hayır",
"confirm.title": "Onay",
"confirm.yes": "Evet",
"error.button": "Tamam",
"error.detail": "İşlem sırasında bir hata oluştu, lütfen daha sonra tekrar deneyin",
"error.message": "Hata oluştu",
"error.title": "Hata",
"update.downloadAndInstall": "İndir ve Yükle",
"update.downloadComplete": "İndirme tamamlandı",
"update.downloadCompleteMessage": "Güncelleme paketi indirildi, hemen yüklemek ister misiniz?",
"update.installLater": "Sonra yükle",
"update.installNow": "Şimdi yükle",
"update.later": "Sonra hatırlat",
"update.newVersion": "Yeni sürüm bulundu",
"update.newVersionAvailable": "Yeni sürüm bulundu: {{version}}",
"update.skipThisVersion": "Bu sürümü atla"
}
+52 -70
View File
@@ -1,71 +1,53 @@
{
"common": {
"checkUpdates": "Güncellemeleri kontrol et..."
},
"dev": {
"devPanel": "Geliştirici Paneli",
"devTools": "Geliştirici Araçları",
"forceReload": "Zorla Yenile",
"openStore": "Depolama dosyasını",
"refreshMenu": "Menüyü yenile",
"reload": "Yenile",
"title": "Geliştir"
},
"edit": {
"copy": "Kopyala",
"cut": "Kes",
"delete": "Sil",
"paste": "Yapıştır",
"redo": "Yinele",
"selectAll": "Tümünü Seç",
"speech": "Ses",
"startSpeaking": "Okumaya Başla",
"stopSpeaking": "Okumayı Durdur",
"title": "Düzenle",
"undo": "Geri Al"
},
"file": {
"preferences": "Tercihler",
"quit": "Çık",
"title": "Dosya"
},
"help": {
"about": "Hakkında",
"githubRepo": "GitHub Deposu",
"reportIssue": "Sorun Bildir",
"title": "Yardım",
"visitWebsite": "Resmi Web Sitesini Ziyaret Et"
},
"macOS": {
"about": "{{appName}} Hakkında",
"devTools": "LobeHub Geliştirici Araçları",
"hide": "{{appName}}'i Gizle",
"hideOthers": "Diğerlerini Gizle",
"preferences": "Tercihler...",
"services": "Hizmetler",
"unhide": "Hepsini Göster"
},
"tray": {
"open": "{{appName}}'i Aç",
"quit": "Çık",
"show": "{{appName}}'i Göster"
},
"view": {
"forceReload": "Zorla Yenile",
"reload": "Yenile",
"resetZoom": "Yakınlaştırmayı Sıfırla",
"title": "Görünüm",
"toggleFullscreen": "Tam Ekrana Geç",
"zoomIn": "Büyüt",
"zoomOut": "Küçült"
},
"window": {
"bringAllToFront": "Tüm Pencereleri Öne Getir",
"close": "Kapat",
"front": "Tüm Pencereleri Öne Getir",
"minimize": "Küçült",
"title": "Pencere",
"toggleFullscreen": "Tam Ekrana Geç",
"zoom": "Yakınlaştır"
}
}
"common.checkUpdates": "Güncellemeleri kontrol et...",
"dev.devPanel": "Geliştirici Paneli",
"dev.devTools": "Geliştirici Araçları",
"dev.forceReload": "Zorla Yenile",
"dev.openStore": "Depolama dosyasını",
"dev.refreshMenu": "Menüyü yenile",
"dev.reload": "Yenile",
"dev.title": "Geliştir",
"edit.copy": "Kopyala",
"edit.cut": "Kes",
"edit.delete": "Sil",
"edit.paste": "Yapıştır",
"edit.redo": "Yinele",
"edit.selectAll": "Tümünü Seç",
"edit.speech": "Ses",
"edit.startSpeaking": "Okumaya Başla",
"edit.stopSpeaking": "Okumayı Durdur",
"edit.title": "Düzenle",
"edit.undo": "Geri Al",
"file.preferences": "Tercihler",
"file.quit": "Çık",
"file.title": "Dosya",
"help.about": "Hakkında",
"help.githubRepo": "GitHub Deposu",
"help.reportIssue": "Sorun Bildir",
"help.title": "Yardım",
"help.visitWebsite": "Resmi Web Sitesini Ziyaret Et",
"macOS.about": "{{appName}} Hakkında",
"macOS.devTools": "LobeHub Geliştirici Araçları",
"macOS.hide": "{{appName}}'i Gizle",
"macOS.hideOthers": "Diğerlerini Gizle",
"macOS.preferences": "Tercihler...",
"macOS.services": "Hizmetler",
"macOS.unhide": "Hepsini Göster",
"tray.open": "{{appName}}'i Aç",
"tray.quit": "Çık",
"tray.show": "{{appName}}'i Göster",
"view.forceReload": "Zorla Yenile",
"view.reload": "Yenile",
"view.resetZoom": "Yakınlaştırmayı Sıfırla",
"view.title": "Görünüm",
"view.toggleFullscreen": "Tam Ekrana Geç",
"view.zoomIn": "Büyüt",
"view.zoomOut": "Küçült",
"window.bringAllToFront": "Tüm Pencereleri Öne Getir",
"window.close": "Kapat",
"window.front": "Tüm Pencereleri Öne Getir",
"window.minimize": "Küçült",
"window.title": "Pencere",
"window.toggleFullscreen": "Tam Ekrana Geç",
"window.zoom": "Yakınlaştır"
}
@@ -1,32 +1,26 @@
{
"actions": {
"add": "Thêm",
"back": "Quay lại",
"cancel": "Hủy",
"close": "Đóng",
"confirm": "Xác nhận",
"delete": "Xóa",
"edit": "Chỉnh sửa",
"more": "Thêm nữa",
"next": "Tiếp theo",
"ok": "Đồng ý",
"previous": "Quay lại",
"refresh": "Tải lại",
"remove": "Gỡ bỏ",
"retry": "Thử lại",
"save": "Lưu",
"search": "Tìm kiếm",
"submit": "Gửi"
},
"app": {
"description": "Nền tảng hợp tác trợ lý AI của bạn",
"name": "LobeHub"
},
"status": {
"error": "Lỗi",
"info": "Thông tin",
"loading": "Đang tải",
"success": "Thành công",
"warning": "Cảnh báo"
}
}
"actions.add": "Thêm",
"actions.back": "Quay lại",
"actions.cancel": "Hủy",
"actions.close": "Đóng",
"actions.confirm": "Xác nhận",
"actions.delete": "Xóa",
"actions.edit": "Chỉnh sửa",
"actions.more": "Thêm nữa",
"actions.next": "Tiếp theo",
"actions.ok": "Đồng ý",
"actions.previous": "Quay lại",
"actions.refresh": "Tải lại",
"actions.remove": "Gỡ bỏ",
"actions.retry": "Thử lại",
"actions.save": "Lưu",
"actions.search": "Tìm kiếm",
"actions.submit": "Gửi",
"app.description": "Nền tảng hợp tác trợ lý AI của bạn",
"app.name": "LobeHub",
"status.error": "Lỗi",
"status.info": "Thông tin",
"status.loading": "Đang tải",
"status.success": "Thành công",
"status.warning": "Cảnh báo"
}
@@ -1,31 +1,23 @@
{
"about": {
"button": "Xác nhận",
"detail": "Một ứng dụng trò chuyện dựa trên mô hình ngôn ngữ lớn",
"message": "{{appName}} {{appVersion}}",
"title": "Về"
},
"confirm": {
"cancel": "Hủy",
"no": "Không",
"title": "Xác nhận",
"yes": "Có"
},
"error": {
"button": "Xác nhận",
"detail": "Đã xảy ra lỗi trong quá trình thực hiện, vui lòng thử lại sau",
"message": "Đã xảy ra lỗi",
"title": "Lỗi"
},
"update": {
"downloadAndInstall": "Tải xuống và cài đặt",
"downloadComplete": "Tải xuống hoàn tất",
"downloadCompleteMessage": "Gói cập nhật đã tải xuống hoàn tất, có muốn cài đặt ngay không?",
"installLater": "Cài đặt sau",
"installNow": "Cài đặt ngay",
"later": "Nhắc nhở sau",
"newVersion": "Phát hiện phiên bản mới",
"newVersionAvailable": "Phát hiện phiên bản mới: {{version}}",
"skipThisVersion": "Bỏ qua phiên bản này"
}
}
"about.button": "Xác nhận",
"about.detail": "Một ứng dụng trò chuyện dựa trên mô hình ngôn ngữ lớn",
"about.message": "{{appName}} {{appVersion}}",
"about.title": "Về",
"confirm.cancel": "Hủy",
"confirm.no": "Không",
"confirm.title": "Xác nhận",
"confirm.yes": "",
"error.button": "Xác nhận",
"error.detail": "Đã xảy ra lỗi trong quá trình thực hiện, vui lòng thử lại sau",
"error.message": "Đã xảy ra lỗi",
"error.title": "Lỗi",
"update.downloadAndInstall": "Tải xuống và cài đặt",
"update.downloadComplete": "Tải xuống hoàn tất",
"update.downloadCompleteMessage": "Gói cập nhật đã tải xuống hoàn tất, có muốn cài đặt ngay không?",
"update.installLater": "Cài đặt sau",
"update.installNow": "Cài đặt ngay",
"update.later": "Nhắc nhở sau",
"update.newVersion": "Phát hiện phiên bản mới",
"update.newVersionAvailable": "Phát hiện phiên bản mới: {{version}}",
"update.skipThisVersion": "Bỏ qua phiên bản này"
}
+52 -70
View File
@@ -1,71 +1,53 @@
{
"common": {
"checkUpdates": "Kiểm tra cập nhật..."
},
"dev": {
"devPanel": "Bảng điều khiển nhà phát triển",
"devTools": "Công cụ phát triển",
"forceReload": "Tải lại cưỡng bức",
"openStore": "Mở tệp lưu trữ",
"refreshMenu": "Làm mới menu",
"reload": "Tải lại",
"title": "Phát triển"
},
"edit": {
"copy": "Sao chép",
"cut": "Cắt",
"delete": "Xóa",
"paste": "Dán",
"redo": "Làm lại",
"selectAll": "Chọn tất cả",
"speech": "Giọng nói",
"startSpeaking": "Bắt đầu đọc",
"stopSpeaking": "Dừng đọc",
"title": "Chỉnh sửa",
"undo": "Hoàn tác"
},
"file": {
"preferences": "Tùy chọn",
"quit": "Thoát",
"title": "Tập tin"
},
"help": {
"about": "Về",
"githubRepo": "Kho lưu trữ GitHub",
"reportIssue": "Báo cáo sự c",
"title": "Trợ giúp",
"visitWebsite": "Truy cập trang web"
},
"macOS": {
"about": "Về {{appName}}",
"devTools": "Công cụ phát triển LobeHub",
"hide": "Ẩn {{appName}}",
"hideOthers": "Ẩn khác",
"preferences": "Cài đặt ưu tiên...",
"services": "Dịch vụ",
"unhide": "Hiện tất cả"
},
"tray": {
"open": "Mở {{appName}}",
"quit": "Thoát",
"show": "Hiện {{appName}}"
},
"view": {
"forceReload": "Tải lại cưỡng bức",
"reload": "Tải lại",
"resetZoom": "Đặt lại thu phóng",
"title": "Xem",
"toggleFullscreen": "Chuyển đổi toàn màn hình",
"zoomIn": "Phóng to",
"zoomOut": "Thu nhỏ"
},
"window": {
"bringAllToFront": "Đưa tất cả cửa sổ lên trước",
"close": "Đóng",
"front": "Đưa tất cả cửa sổ lên trước",
"minimize": "Thu nhỏ",
"title": "Cửa sổ",
"toggleFullscreen": "Chuyển đổi toàn màn hình",
"zoom": "Thu phóng"
}
}
"common.checkUpdates": "Kiểm tra cập nhật...",
"dev.devPanel": "Bảng điều khiển nhà phát triển",
"dev.devTools": "Công cụ phát triển",
"dev.forceReload": "Tải lại cưỡng bức",
"dev.openStore": "Mở tệp lưu trữ",
"dev.refreshMenu": "Làm mới menu",
"dev.reload": "Tải lại",
"dev.title": "Phát triển",
"edit.copy": "Sao chép",
"edit.cut": "Cắt",
"edit.delete": "Xóa",
"edit.paste": "Dán",
"edit.redo": "Làm lại",
"edit.selectAll": "Chọn tất cả",
"edit.speech": "Giọng nói",
"edit.startSpeaking": "Bắt đầu đọc",
"edit.stopSpeaking": "Dừng đọc",
"edit.title": "Chỉnh sửa",
"edit.undo": "Hoàn tác",
"file.preferences": "Tùy chọn",
"file.quit": "Thoát",
"file.title": "Tập tin",
"help.about": "Về",
"help.githubRepo": "Kho lưu trữ GitHub",
"help.reportIssue": "Báo cáo sự cố",
"help.title": "Trợ giúp",
"help.visitWebsite": "Truy cập trang web",
"macOS.about": "Về {{appName}}",
"macOS.devTools": "Công cụ phát triển LobeHub",
"macOS.hide": "Ẩn {{appName}}",
"macOS.hideOthers": "Ẩn khác",
"macOS.preferences": "Cài đặt ưu tiên...",
"macOS.services": "Dịch vụ",
"macOS.unhide": "Hiện tất c",
"tray.open": "Mở {{appName}}",
"tray.quit": "Thoát",
"tray.show": "Hiện {{appName}}",
"view.forceReload": "Tải lại cưỡng bức",
"view.reload": "Tải lại",
"view.resetZoom": "Đặt lại thu phóng",
"view.title": "Xem",
"view.toggleFullscreen": "Chuyển đổi toàn màn hình",
"view.zoomIn": "Phóng to",
"view.zoomOut": "Thu nhỏ",
"window.bringAllToFront": "Đưa tất cả cửa sổ lên trước",
"window.close": "Đóng",
"window.front": "Đưa tất cả cửa sổ lên trước",
"window.minimize": "Thu nhỏ",
"window.title": "Cửa sổ",
"window.toggleFullscreen": "Chuyển đổi toàn màn hình",
"window.zoom": "Thu phóng"
}

Some files were not shown because too many files have changed in this diff Show More