feat: implement i18n support with ConfigProvider integration and locale-aware Thinking component#470
feat: implement i18n support with ConfigProvider integration and locale-aware Thinking component#470IsDyh01 wants to merge 2 commits intoelement-plus-x:mainfrom
Conversation
…le-aware Thinking component
…le-aware Thinking component
📝 WalkthroughWalkthroughThis PR introduces a comprehensive internationalization system with new locale modules supporting Chinese and English, refactors the build configuration to auto-discover locale entry points, enhances ConfigProvider with hierarchical locale management, updates components to use locale utilities, and reorganizes exports to explicitly export all components and types. Changes
Sequence DiagramsequenceDiagram
participant App as App.use(plugin)
participant Install as install(app, options)
participant GlobalConfig as provideGlobalConfig
participant EPGlobal as Element Plus<br/>provideGlobalConfig
participant Comp as Component
participant UseLocale as useLocale()
participant Translate as translate(path)
App->>Install: options: { locale? }
Install->>GlobalConfig: config from options.locale
GlobalConfig->>GlobalConfig: buildConfigProviderContext<br/>(hierarchical merge)
Install->>EPGlobal: resolveElementPlusLocale<br/>(options.locale)
Comp->>UseLocale: hook initialization
UseLocale->>UseLocale: compute lang from<br/>ConfigProvider.locale
UseLocale->>Translate: bind t() to locale
Comp->>Translate: t("elpx.thinking.start")
Translate->>Translate: getLocaleValue<br/>(locale, path)
Translate-->>Comp: translated string
Comp->>Comp: render with locale
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/core/src/stories/Thinking/index.vue (1)
18-19:⚠️ Potential issue | 🟠 MajorExposed API key in source code.
The hardcoded API key
sk-vfjyscildobjnrijtcllnkhtcouidcxdgjxtldzqzeowrbgais visible in the source. Even if this is a free-tier or demo key, it could be scraped and abused. Consider using environment variables or removing it from committed code.🔒 Suggested approach
-const API_KEY = 'sk-vfjyscildobjnrijtcllnkhtcouidcxdgjxtldzqzeowrbga'; +const API_KEY = import.meta.env.VITE_SILICONFLOW_API_KEY || '';Then document that developers need to provide their own key via
.env.local.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/src/stories/Thinking/index.vue` around lines 18 - 19, The file exposes a hardcoded API key via the constant API_KEY; remove the literal and read the key from an environment variable instead (e.g. replace API_KEY assignment with code that uses import.meta.env.VITE_API_KEY or process.env.VUE_APP_API_KEY depending on your build tool), add a runtime check in the Thinking component (or the init function that uses API_KEY) to throw/log a clear error if the env var is missing, and update README/.env.local docs to instruct developers to supply their own key rather than committing secrets.packages/core/src/components/Typewriter/index.vue (1)
26-38:⚠️ Potential issue | 🟡 MinorMultiple Typewriter components may register plugins redundantly on shared markdown-it instance.
When multiple
Typewritercomponents share the samemdinstance (the default behavior when usingBubbleListor multiple siblings without a customConfigProvider), each component independently callsinitMarkdownPlugins()during setup. This causes the same plugins to be registered multiple times on the shared instance. Most markdown-it plugins lack guards against duplicate registration, potentially causing memory leaks or unexpected behavior.Consider:
- Moving plugin registration to
provideGlobalConfig(once per app/config scope) instead of per-component- Tracking already-registered plugins to prevent duplicates, or
- Documenting that custom
mdinstances should be used if registering plugins🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/src/components/Typewriter/index.vue` around lines 26 - 38, The initMarkdownPlugins() function registers plugins on the shared md instance for each Typewriter component, causing duplicate registrations; change initMarkdownPlugins (or registration logic) to guard against repeats by tracking already-registered plugins on the md instance itself (e.g., attach a unique symbol/set like md.value[REGISTERED_PLUGINS] and before calling md.value.use(plugin) check and add to that set), or alternatively move plugin registration into provideGlobalConfig so plugins are applied once per app/config scope; update checks for both configProvider.value.mdPlugins and props.mdPlugins to consult this registry before calling md.value.use.
🧹 Nitpick comments (5)
packages/core/.build/scripts/auto-export-all-components.ts (1)
75-76: Sort the discovered component list before generating the barrel.Sorting the directory names here will make the generated
src/index.tsdeterministic across filesystems and avoid noisy diffs.♻️ Suggested change
- const dirs = await fs.readdir(componentsDir); + const dirs = (await fs.readdir(componentsDir)).sort();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/.build/scripts/auto-export-all-components.ts` around lines 75 - 76, The list of component directories read into the dirs variable from componentsDir is not sorted, causing nondeterministic generated src/index.ts; fix it by sorting the discovered names before generation (e.g., call .sort() or .sort((a,b)=>a.localeCompare(b)) on the array returned by await fs.readdir(componentsDir)) so the barrel creation in auto-export-all-components.ts is deterministic and produces stable diffs.packages/core/src/stories/Thinking/index.vue (1)
64-66: Fix style: brace placement.ESLint reports that the closing curly brace should not appear on the same line as the subsequent block (
} catch). This is a style enforcement from the project's linting rules.🔧 Proposed fix for lines 64-66
- } catch (err) { + } + catch (err) { console.error('解析数据时出错:', err); }🔧 Proposed fix for lines 118-120
- } catch (err) { + } + catch (err) { handleError(err); }Also applies to: 118-120
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/src/stories/Thinking/index.vue` around lines 64 - 66, The catch blocks violate the project's brace-style rule by keeping the closing curly on the same line as the catch; change occurrences where you have "} catch (err) {" to place the closing brace on its own line followed by the catch on the next line (i.e. replace the "} catch (err) {" pattern around the console.error('解析数据时出错:', err); block and the similar block at lines ~118-120 so they become "}" then a new line "catch (err) {" to satisfy the linter.packages/core/src/components/Typewriter/index.vue (1)
79-79: Fix style issues flagged by ESLint.Multiple lines have style violations for
if-newlineandbrace-stylerules.🔧 Proposed fixes
Line 79:
- if (!props.content) return ''; + if (!props.content) + return '';Line 136:
- } else { + } + else {Line 149:
- if (!props.typing || !contentCache.value) return; + if (!props.typing || !contentCache.value) + return;Also applies to: 136-136, 149-149
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/src/components/Typewriter/index.vue` at line 79, The ESLint errors come from single-line if statements like "if (!props.content) return '';" which violate brace-style and if-newline rules; locate each occurrence in the Typewriter component (checks against props.content in setup/render helpers or any function such as setup() or format/formatContent methods) and replace the single-line form with a braced block using a newline for the return, e.g. change to "if (!props.content) { return ''; }" with the return on its own line inside the braces so the statement complies with brace-style and if-newline rules for all occurrences.packages/core/src/locale/element-plus.ts (1)
16-16: Fix style: add newline afterifstatement.ESLint reports that a newline is expected after the
ifcondition per theantfu/if-newlinerule.🔧 Proposed fix
- if (!localeName) return epZhCn; + if (!localeName) + return epZhCn;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/src/locale/element-plus.ts` at line 16, The single-line if statement "if (!localeName) return epZhCn;" violates the antfu/if-newline rule; change it to a multi-line form so the consequent is on the next line (e.g. transform the statement so the condition uses a newline before the return, or expand to a block with braces) — update the occurrence referencing localeName and epZhCn accordingly in the element-plus locale resolution code.packages/core/src/index.ts (1)
38-53: Consider removing.d.tsextension from type import paths.Importing directly from
.d.tsfiles (e.g.,'./components/Attachments/types.d.ts') is valid but unconventional. Some bundlers or TypeScript configurations may not resolve these paths correctly. The standard pattern is to omit the extension or use.tsfiles that export types.♻️ Suggested change
-export type { - AttachmentsEmits, - AttachmentsProps, - FileListProps -} from './components/Attachments/types.d.ts'; +export type { + AttachmentsEmits, + AttachmentsProps, + FileListProps +} from './components/Attachments/types';Apply the same pattern to all type exports (lines 38-121).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/src/index.ts` around lines 38 - 53, The exported type import paths include explicit “.d.ts” extensions (e.g., './components/Attachments/types.d.ts') which is non-standard and can cause resolution issues; update each export statement that references a types.d.ts file (such as the exports for AttachmentsEmits, AttachmentsProps, FileListProps, BubbleEmits, BubbleProps, BubbleListEmits, BubbleListInstance, BubbleListItemProps, BubbleListProps, ConfigProviderProps, MarkdownItPlugin, etc.) to omit the “.d.ts” extension (e.g., './components/Attachments/types') so the bundler/TS resolver will use normal module resolution for those type modules.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/core/.build/scripts/auto-export-all-components.ts`:
- Around line 80-81: The current inline arrow callback used to compute compName
(the dir.replace(/(^\w|-\w)/g, (m: string) => m.replace('-', '').toUpperCase()))
and similar occurrences at the other locations violate consistent-list-newline,
if-newline, and brace-style rules; change these inline single-expression arrow
callbacks to use a full arrow-body with braces and an explicit return (e.g., (m:
string) => { return m.replace('-', '').toUpperCase(); }) and ensure braces and
newlines follow the project's brace-style (opening brace on same line,
statements on new lines) and any multi-item arrays/objects are formatted to
satisfy consistent-list-newline; apply the same pattern to the other affected
symbols/occurrences at the noted locations so the script passes linting.
---
Outside diff comments:
In `@packages/core/src/components/Typewriter/index.vue`:
- Around line 26-38: The initMarkdownPlugins() function registers plugins on the
shared md instance for each Typewriter component, causing duplicate
registrations; change initMarkdownPlugins (or registration logic) to guard
against repeats by tracking already-registered plugins on the md instance itself
(e.g., attach a unique symbol/set like md.value[REGISTERED_PLUGINS] and before
calling md.value.use(plugin) check and add to that set), or alternatively move
plugin registration into provideGlobalConfig so plugins are applied once per
app/config scope; update checks for both configProvider.value.mdPlugins and
props.mdPlugins to consult this registry before calling md.value.use.
In `@packages/core/src/stories/Thinking/index.vue`:
- Around line 18-19: The file exposes a hardcoded API key via the constant
API_KEY; remove the literal and read the key from an environment variable
instead (e.g. replace API_KEY assignment with code that uses
import.meta.env.VITE_API_KEY or process.env.VUE_APP_API_KEY depending on your
build tool), add a runtime check in the Thinking component (or the init function
that uses API_KEY) to throw/log a clear error if the env var is missing, and
update README/.env.local docs to instruct developers to supply their own key
rather than committing secrets.
---
Nitpick comments:
In `@packages/core/.build/scripts/auto-export-all-components.ts`:
- Around line 75-76: The list of component directories read into the dirs
variable from componentsDir is not sorted, causing nondeterministic generated
src/index.ts; fix it by sorting the discovered names before generation (e.g.,
call .sort() or .sort((a,b)=>a.localeCompare(b)) on the array returned by await
fs.readdir(componentsDir)) so the barrel creation in
auto-export-all-components.ts is deterministic and produces stable diffs.
In `@packages/core/src/components/Typewriter/index.vue`:
- Line 79: The ESLint errors come from single-line if statements like "if
(!props.content) return '';" which violate brace-style and if-newline rules;
locate each occurrence in the Typewriter component (checks against props.content
in setup/render helpers or any function such as setup() or format/formatContent
methods) and replace the single-line form with a braced block using a newline
for the return, e.g. change to "if (!props.content) { return ''; }" with the
return on its own line inside the braces so the statement complies with
brace-style and if-newline rules for all occurrences.
In `@packages/core/src/index.ts`:
- Around line 38-53: The exported type import paths include explicit “.d.ts”
extensions (e.g., './components/Attachments/types.d.ts') which is non-standard
and can cause resolution issues; update each export statement that references a
types.d.ts file (such as the exports for AttachmentsEmits, AttachmentsProps,
FileListProps, BubbleEmits, BubbleProps, BubbleListEmits, BubbleListInstance,
BubbleListItemProps, BubbleListProps, ConfigProviderProps, MarkdownItPlugin,
etc.) to omit the “.d.ts” extension (e.g., './components/Attachments/types') so
the bundler/TS resolver will use normal module resolution for those type
modules.
In `@packages/core/src/locale/element-plus.ts`:
- Line 16: The single-line if statement "if (!localeName) return epZhCn;"
violates the antfu/if-newline rule; change it to a multi-line form so the
consequent is on the next line (e.g. transform the statement so the condition
uses a newline before the return, or expand to a block with braces) — update the
occurrence referencing localeName and epZhCn accordingly in the element-plus
locale resolution code.
In `@packages/core/src/stories/Thinking/index.vue`:
- Around line 64-66: The catch blocks violate the project's brace-style rule by
keeping the closing curly on the same line as the catch; change occurrences
where you have "} catch (err) {" to place the closing brace on its own line
followed by the catch on the next line (i.e. replace the "} catch (err) {"
pattern around the console.error('解析数据时出错:', err); block and the similar block
at lines ~118-120 so they become "}" then a new line "catch (err) {" to satisfy
the linter.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0282b277-a312-473c-afd6-1ee5a4038514
📒 Files selected for processing (20)
packages/core/.build/build.tspackages/core/.build/plugins/dts.tspackages/core/.build/scripts/auto-export-all-components.tspackages/core/package.jsonpackages/core/src/components/ConfigProvider/constants.tspackages/core/src/components/ConfigProvider/hooks.tspackages/core/src/components/ConfigProvider/index.vuepackages/core/src/components/ConfigProvider/types.d.tspackages/core/src/components/Thinking/index.vuepackages/core/src/components/Typewriter/index.vuepackages/core/src/components/XMarkdown/types.d.tspackages/core/src/components/XMarkdownAsync/types.d.tspackages/core/src/index.tspackages/core/src/locale/element-plus.tspackages/core/src/locale/index.tspackages/core/src/locale/lang/en.tspackages/core/src/locale/lang/zh-cn.tspackages/core/src/locale/types.tspackages/core/src/locale/use-locale.tspackages/core/src/stories/Thinking/index.vue
| const compName = dir.replace(/(^\w|-\w)/g, (m: string) => | ||
| m.replace('-', '').toUpperCase()); | ||
|
|
||
| m.replace('-', '').toUpperCase() |
There was a problem hiding this comment.
Fix the existing eslint violations in this script.
These lines already violate the configured consistent-list-newline, if-newline, and brace-style rules, so the helper itself stays red before it even formats the generated file.
🧹 Minimal lint-fix patch
- const compName = dir.replace(/(^\w|-\w)/g, (m: string) =>
- m.replace('-', '').toUpperCase()
- );
+ const compName = dir.replace(/(^\w|-\w)/g, (m: string) => m.replace('-', '').toUpperCase());
- if (!typeNames.length) return [];
+ if (!typeNames.length) {
+ return [];
+ }
- } catch (error) {
+ }
+ catch (error) {
console.warn('⚠️ Eslint formatting failed:', error);
}
- } catch (error) {
+ }
+ catch (error) {
console.error('❌ Error generating auto-entry files:', error);
exit(1);
}Also applies to: 101-101, 144-147
🧰 Tools
🪛 ESLint
[error] 80-81: Should not have line breaks between items, in node CallExpression
(antfu/consistent-list-newline)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/core/.build/scripts/auto-export-all-components.ts` around lines 80 -
81, The current inline arrow callback used to compute compName (the
dir.replace(/(^\w|-\w)/g, (m: string) => m.replace('-', '').toUpperCase())) and
similar occurrences at the other locations violate consistent-list-newline,
if-newline, and brace-style rules; change these inline single-expression arrow
callbacks to use a full arrow-body with braces and an explicit return (e.g., (m:
string) => { return m.replace('-', '').toUpperCase(); }) and ensure braces and
newlines follow the project's brace-style (opening brace on same line,
statements on new lines) and any multi-item arrays/objects are formatted to
satisfy consistent-list-newline; apply the same pattern to the other affected
symbols/occurrences at the noted locations so the script passes linting.
Summary by CodeRabbit
Release Notes
New Features
Chores