Skip to content

refactor(web): timezone select options display with i18n support#2497

Open
bowenliang123 wants to merge 4 commits intoagentscope-ai:mainfrom
bowenliang123:timezone-i18n
Open

refactor(web): timezone select options display with i18n support#2497
bowenliang123 wants to merge 4 commits intoagentscope-ai:mainfrom
bowenliang123:timezone-i18n

Conversation

@bowenliang123
Copy link
Copy Markdown
Contributor

@bowenliang123 bowenliang123 commented Mar 29, 2026

Description

[Describe what this PR does and why]

  • Replace static timezone list with @vvo/tzdb library for accurate offset data, to avoid hardcoded display text for timezones

  • Add i18n support - timezone names now display in current page language (zh/en/ru/ja)

  • New display format: Localized Name (+08:00, Asia/Shanghai) instead of Asia/Shanghai (UTC+8)

  • Before:

image
  • After:
image

Related Issue:* Fixes #(issue_number) or Relates to #(issue_number)

Security Considerations: [If applicable, e.g. channel auth, env/config handling]

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • Refactoring

Component(s) Affected

  • Core / Backend (app, agents, config, providers, utils, local_models)
  • Console (frontend web UI)
  • Channels (DingTalk, Feishu, QQ, Discord, iMessage, etc.)
  • Skills
  • CLI
  • Documentation (website)
  • Tests
  • CI/CD
  • Scripts / Deploy

Checklist

  • I ran pre-commit run --all-files locally and it passes
  • If pre-commit auto-fixed files, I committed those changes and reran checks
  • I ran tests locally (pytest or as relevant) and they pass
  • Documentation updated (if needed)
  • Ready for review

Testing

[How to test these changes]

Local Verification Evidence

pre-commit run --all-files
# paste summary result

pytest
# paste summary result

Additional Notes

[Optional: any other context]

Copilot AI review requested due to automatic review settings March 29, 2026 14:56
@github-actions
Copy link
Copy Markdown

Welcome to CoPaw! 🐾

Hi @bowenliang123, this is your 7th Pull Request.

🙌 Join Developer Community

Thanks so much for your contribution! We'd love to invite you to join the official CoPaw developer group! You can find the Discord and DingTalk group links under the "Developer Community" section on our docs page:
https://copaw.agentscope.io/docs/community

We truly appreciate your enthusiasm—and look forward to your future contributions! 😊

We'll review your PR soon.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request replaces the static timezone list with a dynamic, localized implementation using the @vvo/tzdb library and a new useTimezoneOptions hook. This update enables translated timezone labels with UTC offsets in the agent configuration and cron job components. Feedback suggests improving the scalability of the locale mapping and refactoring the timezone mapping logic to avoid redundancy.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors the console’s timezone <Select> options to be generated dynamically (with current offsets) and localized via the current i18n language, replacing the prior hardcoded label strings.

Changes:

  • Replaced static timezone option labels with @vvo/tzdb-backed option generation (getTimezoneOptions) and localized display names via Intl.DateTimeFormat.
  • Introduced useTimezoneOptions() hook and switched CronJobs + Agent Config selects to use it.
  • Updated exports/imports to remove TIMEZONE_OPTIONS re-exports from CronJobs components.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
console/src/pages/Control/CronJobs/components/index.ts Stops re-exporting TIMEZONE_OPTIONS from CronJobs components.
console/src/pages/Control/CronJobs/components/constants.ts Removes passthrough export of timezone options; keeps form defaults only.
console/src/pages/Control/CronJobs/components/JobDrawer.tsx Switches timezone <Select> options to useTimezoneOptions().
console/src/pages/Agent/Config/components/ReactAgentCard.tsx Switches timezone <Select> options to useTimezoneOptions().
console/src/hooks/useTimezoneOptions.ts Adds hook to memoize timezone options by current i18n.language.
console/src/constants/timezone.ts Implements tzdb-backed, localized timezone option generation.
console/package.json Adds @vvo/tzdb dependency.
console/package-lock.json Locks @vvo/tzdb dependency.
Files not reviewed (1)
  • console/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@xieyxclack
Copy link
Copy Markdown
Member

Thank you for your contribution!
Please format the code via cd console && npm run format.

Or refer to https://github.com/agentscope-ai/CoPaw/blob/main/CONTRIBUTING.md#4-code-and-quality

Copilot AI review requested due to automatic review settings March 29, 2026 16:25
@bowenliang123
Copy link
Copy Markdown
Contributor Author

Fixed the lint issues. Sorry to forgot to reformat the code again.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 8 changed files in this pull request and generated 4 comments.

Files not reviewed (1)
  • console/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 231 to 235
.toLowerCase()
.includes(input.toLowerCase())
}
options={TIMEZONE_OPTIONS}
options={useTimezoneOptions()}
/>
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useTimezoneOptions() is a React hook; calling it directly inside JSX props (in the options={...} expression) will trip react-hooks/rules-of-hooks and can break hook ordering if this render path ever becomes conditional. Call the hook once at the top of the component (e.g., assign to a timezoneOptions const) and pass that variable to Select instead.

Copilot uses AI. Check for mistakes.
Comment on lines 63 to 67
.toLowerCase()
.includes(input.toLowerCase())
}
options={TIMEZONE_OPTIONS}
options={useTimezoneOptions()}
onChange={onTimezoneChange}
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useTimezoneOptions() is a React hook; calling it inline in options={useTimezoneOptions()} violates react-hooks/rules-of-hooks (this repo enables the recommended react-hooks rules) and may fail linting. Invoke the hook once near the top of ReactAgentCard and pass the resulting array to the Select.

Copilot uses AI. Check for mistakes.

export function useTimezoneOptions(): TimezoneOption[] {
const { i18n } = useTranslation();
return useMemo(() => getTimezoneOptions(i18n.language), [i18n.language]);
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i18n.language can include region subtags (e.g. en-US). In this repo App.tsx normalizes language via lng.split("-")[0] when deriving locale. Consider normalizing here too (and/or using i18n.resolvedLanguage) before passing into getTimezoneOptions, otherwise the locale map in getLocalizedName will fall back to English unexpectedly.

Suggested change
return useMemo(() => getTimezoneOptions(i18n.language), [i18n.language]);
const language = i18n.resolvedLanguage ?? i18n.language;
return useMemo(
() => {
const locale = (language ?? "en").split("-")[0];
return getTimezoneOptions(locale);
},
[language],
);

Copilot uses AI. Check for mistakes.
Comment on lines +50 to +57
.sort((a, b) => a.currentTimeOffsetInMinutes - b.currentTimeOffsetInMinutes)
.map((tz) => {
const value = tz.name === "Etc/UTC" ? "UTC" : tz.name;
return {
value,
label: `${getLocalizedName(tz.name, lang)} (${
tz.currentTimeFormat.split(" ")[0]
}, ${value})`,
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The offset portion of the label is derived from tz.currentTimeFormat.split(" ")[0], which is brittle and depends on the library’s string format (and may include a UTC prefix, differing from the intended +08:00 display). Prefer formatting tz.currentTimeOffsetInMinutes into a ±HH:MM string directly so the UI output is stable and matches the desired format.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants