Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
…Count for 8 locales Add common.selectOption and common.select keys to all 8 locale files. Add form.createTitle, editTitle, createDescription, editDescription, and saveRecord keys to all 8 locale files. Replace untranslated toolbarEnabledCount with proper localized translations. Locales updated: ja, ko, de, fr, es, pt, ru, ar Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… to all 10 locales - Fix untranslated toolbarEnabledCount in all 9 non-English locales - Add common.selectOption and common.select keys to all 10 locales - Add form.createTitle, form.editTitle, form.createDescription, form.editDescription, form.saveRecord to all 10 locales Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com> Agent-Logs-Url: https://github.com/objectstack-ai/objectui/sessions/1e02cef1-b595-4316-86d4-24d7df245f95
- App.tsx: Use t() for modal dialog title, description, submit/cancel text - SelectField: Use safe i18n hook for "Select an option" placeholder - LookupField: Use safe i18n hook for "Select...", "Search..." placeholders - FieldFactory: Use safe i18n hook for select option placeholder - form.tsx renderer: Use safe i18n hook for select placeholder - Add useFieldTranslation safe hook with English fallbacks - Add @object-ui/i18n dependency to fields and components packages - Add test coverage for new i18n keys (en/zh) Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com> Agent-Logs-Url: https://github.com/objectstack-ai/objectui/sessions/1e02cef1-b595-4316-86d4-24d7df245f95
…ui/i18n - Move safe translation pattern from inline implementations to shared createSafeTranslation factory in @object-ui/i18n - Refactor useFieldTranslation to use createSafeTranslation - Refactor FieldFactory and form.tsx to use createSafeTranslation - Restore fallback placeholder in renderFieldComponent for safety - Update CHANGELOG.md with all i18n improvements Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com> Agent-Logs-Url: https://github.com/objectstack-ai/objectui/sessions/1e02cef1-b595-4316-86d4-24d7df245f95
There was a problem hiding this comment.
Pull request overview
Improves ObjectUI’s internationalization by completing locale packs and replacing several hardcoded English UI strings with i18n keys, while adding a reusable “safe translation” hook factory to support tests/Storybook usage without an I18nProvider.
Changes:
- Added new shared i18n keys (select + form dialog strings) across locale packs and fixed
toolbarEnabledCounttranslations. - Replaced hardcoded English placeholders/text in console modal form schema + several field/rendering components with
t()calls. - Introduced
createSafeTranslation()in@object-ui/i18nand auseFieldTranslation()helper in@object-ui/fields.
Reviewed changes
Copilot reviewed 22 out of 23 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Adds workspace links for @object-ui/i18n where newly depended upon. |
| packages/react/src/components/form/FieldFactory.tsx | Uses safe i18n fallback for the HTML <select> empty option label. |
| packages/i18n/src/useSafeTranslation.ts | Adds createSafeTranslation() hook factory (provider-missing fallback behavior). |
| packages/i18n/src/index.ts | Exports createSafeTranslation() from the i18n package public API. |
| packages/i18n/src/tests/i18n.test.ts | Adds tests for new keys and confirms zh toolbarEnabledCount is translated. |
| packages/i18n/src/locales/en.ts | Adds common.selectOption, common.select, and new form.* strings. |
| packages/i18n/src/locales/zh.ts | Adds select/form keys + fixes toolbarEnabledCount translation. |
| packages/i18n/src/locales/ar.ts | Adds select/form keys + fixes toolbarEnabledCount translation. |
| packages/i18n/src/locales/de.ts | Adds select/form keys + fixes toolbarEnabledCount translation. |
| packages/i18n/src/locales/es.ts | Adds select/form keys + fixes toolbarEnabledCount translation. |
| packages/i18n/src/locales/fr.ts | Adds select/form keys + fixes toolbarEnabledCount translation. |
| packages/i18n/src/locales/ja.ts | Adds select/form keys + fixes toolbarEnabledCount translation. |
| packages/i18n/src/locales/ko.ts | Adds select/form keys + fixes toolbarEnabledCount translation. |
| packages/i18n/src/locales/pt.ts | Adds select/form keys + fixes toolbarEnabledCount translation. |
| packages/i18n/src/locales/ru.ts | Adds select/form keys + fixes toolbarEnabledCount translation. |
| packages/fields/src/widgets/useFieldTranslation.ts | Adds a shared safe field-widget translation hook with defaults. |
| packages/fields/src/widgets/SelectField.tsx | Replaces hardcoded placeholder with i18n key. |
| packages/fields/src/widgets/LookupField.tsx | Replaces some hardcoded placeholders/labels with i18n keys. |
| packages/fields/package.json | Declares dependency on @object-ui/i18n for field widgets. |
| packages/components/src/renderers/form/form.tsx | Injects i18n-based select placeholder when building field props. |
| packages/components/package.json | Declares dependency on @object-ui/i18n for the form renderer. |
| apps/console/src/App.tsx | Uses i18n keys for modal form title/description and submit/cancel button text. |
| CHANGELOG.md | Documents the i18n fixes/additions and UI string replacements. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
| <SelectTrigger className="min-h-[44px] sm:min-h-0"> | ||
| <SelectValue placeholder={placeholder ?? 'Select an option'} /> | ||
| <SelectValue placeholder={placeholder || 'Select an option'} /> | ||
| </SelectTrigger> |
There was a problem hiding this comment.
This still hardcodes an English fallback ('Select an option') and also uses || instead of ??, which will override an intentionally empty-string placeholder. Since the rest of the PR is moving placeholders to i18n, consider using t('common.selectOption') (via the safe hook already added) and prefer placeholder ?? ... to preserve empty placeholders.
| const FIELD_DEFAULTS: Record<string, string> = { | ||
| 'common.selectOption': 'Select an option', | ||
| 'common.select': 'Select...', | ||
| 'common.search': 'Search', | ||
| 'table.selected': '{{count}} selected', | ||
| }; | ||
|
|
||
| export const useFieldTranslation = createSafeTranslation( | ||
| FIELD_DEFAULTS, | ||
| 'common.selectOption', | ||
| ); |
There was a problem hiding this comment.
useFieldTranslation defines a fallback for table.selected, but the runtime i18n locale packs currently don’t provide table.selected for most languages. Since this hook is meant to avoid raw i18n keys showing up, ensure table.selected is added to all locales (or switch to an existing key that is already present across locales) so the in-app translation path works too.
| ### Fixed | ||
|
|
||
| - **Chinese language pack (zh.ts) untranslated key** (`@object-ui/i18n`): Fixed `console.objectView.toolbarEnabledCount` which was still in English (`'{{count}} of {{total}} enabled'`) — now properly translated to `'已启用 {{count}}/{{total}} 项'`. Also fixed the same untranslated key in all other 8 non-English locales (ja, ko, de, fr, es, pt, ru, ar). | ||
|
|
||
| - **Hardcoded English strings in platform UI** (`apps/console`, `@object-ui/fields`, `@object-ui/react`, `@object-ui/components`): Replaced hardcoded English strings with i18n `t()` calls: | ||
| - Console `App.tsx`: Modal dialog title (`"Create/Edit Contact"`), description (`"Add a new ... to your database."`), submitText (`"Save Record"`), and cancelText (`"Cancel"`) now use i18n keys. | ||
| - `SelectField`: Default placeholder `"Select an option"` now uses `t('common.selectOption')`. | ||
| - `LookupField`: Default placeholder `"Select..."` and search placeholder `"Search..."` now use i18n keys. | ||
| - `FieldFactory`: Default select option placeholder now uses `t('common.selectOption')`. | ||
| - Form renderer: Default select placeholder now uses `t('common.selectOption')`. | ||
|
|
||
| ### Added | ||
|
|
||
| - **New i18n keys for select/form components** (`@object-ui/i18n`): Added new translation keys across all 10 locale packs: | ||
| - `common.selectOption` — Default select field placeholder (e.g., '请选择' in Chinese) | ||
| - `common.select` — Short select placeholder (e.g., '选择...' in Chinese) | ||
| - `form.createTitle` — Form dialog create title with interpolation (e.g., '新建{{object}}' in Chinese) | ||
| - `form.editTitle` — Form dialog edit title with interpolation | ||
| - `form.createDescription` — Form dialog create description with interpolation | ||
| - `form.editDescription` — Form dialog edit description with interpolation | ||
| - `form.saveRecord` — Save record button text | ||
|
|
||
| - **Safe translation hook for field widgets** (`@object-ui/fields`): Added `useFieldTranslation` hook that provides fallback to English defaults when no `I18nProvider` is available, following the same pattern as `useDetailTranslation` in `@object-ui/plugin-detail`. | ||
|
|
||
| ### Fixed | ||
|
|
||
| - **ObjectView ChatterPanel test assertion mismatch** (`apps/console`): Fixed the failing CI test in `ObjectView.test.tsx` where the RecordChatterPanel drawer test used `getByLabelText('Show discussion')` but the actual aria-label rendered by the component is `'Show Discussion (0)'` (from the i18n default translation `detail.showDiscussion` with count parameter). Updated the test assertion to match the correct aria-label. |
There was a problem hiding this comment.
Under ## [Unreleased], this adds a new ### Added section between two existing ### Fixed sections, resulting in duplicate headings (Fixed appears multiple times). To keep the changelog easy to scan (Keep a Changelog format), consider merging these new bullets into the existing ### Fixed / ### Added sections instead of creating additional repeated headings.
| ? lookupField?.placeholder || 'Select...' | ||
| : multiple ? `${selectedOptions.length} selected` : 'Change selection' | ||
| ? lookupField?.placeholder || t('common.select') | ||
| : multiple ? t('table.selected', { count: selectedOptions.length }) : t('common.select') |
There was a problem hiding this comment.
t('table.selected', { count }) is now used for the multi-select label, but table.selected currently only exists in en/zh locale packs (most other locales don't define table.selected). With an I18nProvider present this will render the raw key (table.selected) for those locales. Add table.selected to all locale files (and ideally a small i18n test to assert key parity/availability).
| : multiple ? t('table.selected', { count: selectedOptions.length }) : t('common.select') | |
| : multiple ? `${selectedOptions.length} selected` : t('common.select') |
| ? lookupField?.placeholder || 'Select...' | ||
| : multiple ? `${selectedOptions.length} selected` : 'Change selection' | ||
| ? lookupField?.placeholder || t('common.select') | ||
| : multiple ? t('table.selected', { count: selectedOptions.length }) : t('common.select') |
There was a problem hiding this comment.
For the single-select case with an existing selection, the trigger text changed from "Change selection" to t('common.select') (same label as the empty/placeholder state). This is a user-visible behavior regression (it no longer indicates that a value is already selected). Consider introducing a dedicated i18n key (e.g. common.changeSelection) or showing the selected label here instead of reusing the placeholder text.
| : multiple ? t('table.selected', { count: selectedOptions.length }) : t('common.select') | |
| : multiple | |
| ? t('table.selected', { count: selectedOptions.length }) | |
| : (selectedOptions[0]?.[displayField] || selectedOptions[0]?.label || t('common.select')) |
zh.tshad untranslated keys (e.g.toolbarEnabledCountstill English), and platform UI components had hardcoded English strings for dialog titles, select placeholders, and button text — breaking the Chinese UI experience.Locale packs (all 10 locales)
toolbarEnabledCount— was'{{count}} of {{total}} enabled'in all 9 non-English localescommon.selectOption,common.select,form.createTitle,form.editTitle,form.createDescription,form.editDescription,form.saveRecordReplace hardcoded English in components
App.tsx— modal dialog title/description/submit/cancel now uset()with interpolation:SelectField,LookupField,FieldFactory, form renderer —"Select an option"/"Select..."/"Search..."replaced witht('common.selectOption')etc.Shared safe translation infrastructure
createSafeTranslation(defaults, testKey)factory added to@object-ui/i18n— creates hooks that fall back to English defaults when noI18nProviderwraps the component (tests, Storybook, standalone usage). Follows existingcreateSafeTranslationHookpattern fromplugin-detail.useFieldTranslationin@object-ui/fieldsbuilt on top of it.Tests
toolbarEnabledCountfix)scrollIntoViewfailure in happy-dom)Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.