-
Notifications
You must be signed in to change notification settings - Fork 696
feat(i18n): Add translation wrappers to remaining Vue components #2856
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
eca5eb6 to
30a4390
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #2856 +/- ##
========================================
Coverage 39.68% 39.68%
========================================
Files 121 121
Lines 4926 4926
========================================
Hits 1955 1955
Misses 2971 2971 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
- Assignment Rules: Added __ import and translated ticketRoutingOptions - EmailNotifications: Added __ import to Notification.vue - FieldDependency: Translated all user-facing strings in criteria, fields selection, and value selection components - Holiday: Full translation of calendar, list, table view, modals, and recurring holidays components This is part of the effort to add i18n support across the codebase as requested in PR frappe#2836.
- SLA: Translated all modals (EditResponseResolution, WorkDay), list items, priorities, status, workdays, and assignment conditions - Agents: Translated role labels, dropdown options, toast messages - AgentCard: Translated inactive badge - Email: Translated config fields, labels, descriptions, validation messages, and service info texts - InviteAgents: Translated role labels, toast messages - EmailAccountList: Added __ import
- General: Added __ import to LogoUpload and WorkflowKnowledgebaseSettings - Teams: Translated validation messages in NewTeam, button labels in TeamEdit and RenameTeamModal
- AssignmentModal: Translated title and placeholder - ConfirmDialog: Translated confirm button label - ViewModal: Translated title, placeholder, and button labels - TicketMergeModal: Translated all strings and messages - TicketSplitModal: Translated all strings and messages
- CategoryModal: Translated title and action button labels - NewCustomerDialog: Translated title, labels, and messages
- MergeCategoryModal.vue - MoveToCategoryModal.vue - TicketSubjectModal.vue - AddNewAgentsDialog.vue - CustomerDialog.vue - CallLogDetailModal.vue - SettingsModal.vue (add missing import)
- InvalidPage.vue - Contacts.vue - Customers.vue - CallLogs.vue - Articles.vue - KnowledgeBaseCustomer.vue
- TicketConversation.vue - TicketAgent.vue - TicketCustomerTemplateFields.vue
- TicketTextEditor.vue - TicketBreadcrumbs.vue
- Autocomplete.vue - EmptyState.vue - CommunicationArea.vue - TextEditor.vue - EmailEditor.vue
- UniInput.vue - ListRows.vue
d39943b to
848eec1
Compare
848eec1 to
610b3c6
Compare
|
are you using AI for it? if yes can you share the prompt? |
|
Hi @RitvikSardana 👋 Yes! For tedious and repetitive tasks like wrapping 500+ strings across 100+ files with translation functions, AI is a huge time saver. I'm using Claude Code (Anthropic's CLI tool) with a multi-agent workflow: 3-Agent Workflow:
This approach ensures consistency and catches edge cases like template literals, computed properties, and nested strings. 📋 Click to see the full Claude Code promptVue i18n Translation WorkflowYou will perform internationalization (i18n) on Vue.js files using a 3-phase approach. Phase 1: Scanner AgentScan the codebase to identify all Vue files with hardcoded user-facing strings. Task:
Output format: ## Files to translate
### src/components/Example.vue
- Line 15: `label="Submit"` → `:label="__('Submit')"`
- Line 42: `toast.success("Saved!")` → `toast.success(__("Saved!"))`Phase 2: Modifier AgentApply translations systematically based on the scan report. Rules:
Examples: // Before
<Button label="Save" />
toast.error("Failed to load data");
const title = `Hello ${name}`;
// After
<Button :label="__('Save')" />
toast.error(__("Failed to load data"));
const title = __("Hello {0}", [name]);Phase 3: Verifier AgentVerify all modifications are correct. Checklist:
Run build to verify: |
|
Hello seems like a few translations are pending @bvisible |
- Tickets.vue: Translate 'Create' button - Sidebar.vue: Translate 'Frappe Helpdesk' title - CallLogModal.vue: Translate phone placeholders - CommunicationArea.vue: Translate email/comment placeholders - NewCustomerDialog.vue: Translate example placeholders - CustomerDialog.vue: Translate domain placeholder - ContactDialog.vue: Translate email/phone placeholders - SearchComplete.vue: Translate 'Select an option' placeholder
| label: __("Default Incoming"), | ||
| name: "default_incoming", | ||
| type: "checkbox", | ||
| description: | ||
| "If enabled, all replies to your company (eg: [email protected]) will come to this account. Note: Only one account can be default incoming.", | ||
| description: __( | ||
| "If enabled, all replies to your company (eg: [email protected]) will come to this account. Note: Only one account can be default incoming." | ||
| ), | ||
| }, | ||
| { | ||
| label: "Default Outgoing", | ||
| label: __("Default Outgoing"), | ||
| name: "default_outgoing", | ||
| type: "checkbox", | ||
| description: | ||
| "If enabled, all outgoing emails will be sent from this account. Note: Only one account can be default outgoing.", | ||
| description: __( | ||
| "If enabled, all outgoing emails will be sent from this account. Note: Only one account can be default outgoing." | ||
| ), | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of editing the label here, better to translate it in EmailAdd or EmailEdit component
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done - reverted in 663bc51
| label: __("Account Name"), | ||
| name: "email_account_name", | ||
| type: "text", | ||
| placeholder: "Support / Sales", | ||
| }, | ||
| { | ||
| label: "Email ID", | ||
| label: __("Email ID"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Translate the message inside the UI only, not here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done - reverted in 663bc51
| }); | ||
| }; | ||
|
|
||
| const columns = computed(() => [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to do it in UI
{{ __(column.label) }} => line 21
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done - moved translation to template line 21 in 663bc51
desk/src/components/ListRows.vue
Outdated
| }); | ||
| if (group.group.label == "General") { | ||
| _actions = _actions.filter((action) => action.label === "Add New Article"); | ||
| if (group.group.label == __("General")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
never do this, comparing with translated string is always wrong
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done - removed translated string comparison in 663bc51
desk/src/components/ListRows.vue
Outdated
| @@ -14,9 +14,9 @@ | |||
| <span>{{ group.group.label }}</span> | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add translations here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done - added translation in 663bc51
desk/src/components/IconPicker.vue
Outdated
| } | ||
| if (!Object.keys(groups).length) { | ||
| groups["No results"] = []; | ||
| groups[__("No results")] = []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done - reverted in 663bc51
|
|
||
| withDefaults(defineProps<Props>(), { | ||
| title: "No Data Found", | ||
| title: "", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why?
can revert it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done - reverted in 663bc51
| const { | ||
| label = "Discard", | ||
| hideDialog = false, | ||
| title = "Discard?", | ||
| message = "Are you sure you want to discard this?", | ||
| } = defineProps<{ | ||
| label?: string; | ||
| hideDialog?: boolean; | ||
| title?: string; | ||
| message?: string; | ||
| }>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why have you removed these defaults?
Please revert this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done - reverted in 663bc51
|
Please add translations in
and other components |
- Revert emailConfig.ts: translate in UI, not config - Revert IconPicker.vue: don't use translated string as object key - Revert EmptyState.vue: keep original default handling - Revert DiscardButton.vue: keep original defaults - Fix ListRows.vue: don't compare against translated strings - Fix SlaPriorityList.vue: translate in template, not data - Fix savedReplies.ts: remove translations from config - Add translations to ColumnSettings.vue
- Reload.vue: Translate 'Refresh' - MobileSidebar.vue: Translate 'Notifications', 'Dashboard' - CommentTextEditor.vue: Translate 'Discard'
- Telephony.vue: translate form labels and section headers - AssignmentRuleView.vue: translate button labels, toast messages and dialog - CFCondition.vue and CFConditions.vue: translate button labels - MultiSelectCombobox.vue: translate Select All and Clear buttons - EmptyState.vue: translate Create and No Data Found
Summary
__()translation wrappers to all remaining Vue components in the frontendComponents translated:
Translation pattern used:
Test plan
yarn build)