From fa1e171b64726d9664af2ad69db19189d84eb0cf Mon Sep 17 00:00:00 2001 From: cavidelizade Date: Thu, 16 Jul 2026 14:44:15 +0400 Subject: [PATCH] fix(i18n): add missing dynamic-key catalogs, fix plurals and admin sections Several surfaces were migrated by passing an inline English default to t() without adding the key to the catalog, so Azerbaijani silently fell back to English. Add the missing key families (home widgets, notification/pages tabs, project sidebar nav, saved-view date presets, page-editor colour names, slash menu and toolbar, notification-preference rows, estimate types) to both catalogs and register them in dynamicKeys.ts. Also: - InstanceAdminLayout queries instanceAdmin.section..label/.desc but the catalog only had the flat instanceAdmin.section. keys, so the Azerbaijani section labels never showed. Replace the flat keys with .label/.desc (with descriptions) in both catalogs and dynamicKeys.ts. - Fix broken English plurals: "{{count}} days/hours/minutes ago" (were singular in _other), "{{count}} Module"/"{{count}} retry" (_one were plural). - The work-item description editor's slash menu rendered its titles/descriptions and empty state as raw English (vanilla DOM in a .ts file). Route them through i18n, reusing the page editor's editor.slash.* keys. en/az stay at full parity (2211 keys each, none empty); the extractor reports no untracked strings. Closes #318 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../work-item/editorSlashCommands.ts | 23 ++- apps/web/src/i18n/dynamicKeys.ts | 150 ++++++++++++++++-- apps/web/src/i18n/locales/az/translation.json | 121 ++++++++++++-- apps/web/src/i18n/locales/en/translation.json | 125 +++++++++++++-- 4 files changed, 382 insertions(+), 37 deletions(-) diff --git a/apps/web/src/components/work-item/editorSlashCommands.ts b/apps/web/src/components/work-item/editorSlashCommands.ts index e594d998..671685f8 100644 --- a/apps/web/src/components/work-item/editorSlashCommands.ts +++ b/apps/web/src/components/work-item/editorSlashCommands.ts @@ -2,8 +2,11 @@ import { Extension } from '@tiptap/core'; import Suggestion from '@tiptap/suggestion'; import type { Editor, Range } from '@tiptap/core'; +import i18n from '../../i18n'; interface SlashCommand { + /** i18n key stem, shared with the page editor's slash menu (editor.slash..*). */ + key: string; title: string; description: string; icon: string; @@ -12,6 +15,7 @@ interface SlashCommand { const COMMANDS: SlashCommand[] = [ { + key: 'heading1', title: 'Heading 1', description: 'Big section heading', icon: 'H1', @@ -19,6 +23,7 @@ const COMMANDS: SlashCommand[] = [ editor.chain().focus().deleteRange(range).toggleHeading({ level: 1 }).run(), }, { + key: 'heading2', title: 'Heading 2', description: 'Medium section heading', icon: 'H2', @@ -26,6 +31,7 @@ const COMMANDS: SlashCommand[] = [ editor.chain().focus().deleteRange(range).toggleHeading({ level: 2 }).run(), }, { + key: 'heading3', title: 'Heading 3', description: 'Small section heading', icon: 'H3', @@ -33,6 +39,7 @@ const COMMANDS: SlashCommand[] = [ editor.chain().focus().deleteRange(range).toggleHeading({ level: 3 }).run(), }, { + key: 'bulletList', title: 'Bullet list', description: 'A simple bullet list', icon: '••', @@ -40,6 +47,7 @@ const COMMANDS: SlashCommand[] = [ editor.chain().focus().deleteRange(range).toggleBulletList().run(), }, { + key: 'numberedList', title: 'Numbered list', description: 'An ordered list', icon: '1.', @@ -47,6 +55,7 @@ const COMMANDS: SlashCommand[] = [ editor.chain().focus().deleteRange(range).toggleOrderedList().run(), }, { + key: 'quote', title: 'Quote', description: 'Block quote', icon: '❝', @@ -54,6 +63,7 @@ const COMMANDS: SlashCommand[] = [ editor.chain().focus().deleteRange(range).toggleBlockquote().run(), }, { + key: 'codeBlock', title: 'Code block', description: 'Fenced code', icon: '', @@ -61,6 +71,7 @@ const COMMANDS: SlashCommand[] = [ editor.chain().focus().deleteRange(range).toggleCodeBlock().run(), }, { + key: 'divider', title: 'Divider', description: 'Horizontal rule', icon: '—', @@ -69,6 +80,10 @@ const COMMANDS: SlashCommand[] = [ }, ]; +/** Localised label/description for a slash command, shared with the page editor. */ +const cmdTitle = (c: SlashCommand) => i18n.t(`editor.slash.${c.key}.title`, c.title); +const cmdDesc = (c: SlashCommand) => i18n.t(`editor.slash.${c.key}.subtitle`, c.description); + /** * TipTap extension that opens a slash-command palette when the user types `/`. * Like the @-mention popup it uses a vanilla DOM list — keyboard nav (↑↓ + Enter) @@ -96,7 +111,7 @@ export function createSlashCommands() { const q = query.toLowerCase().trim(); if (!q) return COMMANDS; return COMMANDS.filter( - (c) => c.title.toLowerCase().includes(q) || c.description.toLowerCase().includes(q), + (c) => cmdTitle(c).toLowerCase().includes(q) || cmdDesc(c).toLowerCase().includes(q), ); }, render: () => { @@ -111,7 +126,7 @@ export function createSlashCommands() { popup.innerHTML = ''; if (currentItems.length === 0) { const empty = document.createElement('div'); - empty.textContent = 'No matches'; + empty.textContent = i18n.t('editor.slash.noMatch', 'No matches'); empty.className = 'px-3 py-2 text-xs text-(--txt-tertiary)'; popup.appendChild(empty); return; @@ -133,10 +148,10 @@ export function createSlashCommands() { body.className = 'min-w-0 flex-1'; const t = document.createElement('span'); t.className = 'block truncate'; - t.textContent = cmd.title; + t.textContent = cmdTitle(cmd); const d = document.createElement('span'); d.className = 'block truncate text-[11px] text-(--txt-tertiary)'; - d.textContent = cmd.description; + d.textContent = cmdDesc(cmd); body.appendChild(t); body.appendChild(d); btn.appendChild(body); diff --git a/apps/web/src/i18n/dynamicKeys.ts b/apps/web/src/i18n/dynamicKeys.ts index 32aa53b8..8c5297b6 100644 --- a/apps/web/src/i18n/dynamicKeys.ts +++ b/apps/web/src/i18n/dynamicKeys.ts @@ -101,15 +101,34 @@ export function registerDynamicKeys(t: TFunction) { t('settings.webhooks.event.issue_comment.label', 'Issue comments'); t('settings.webhooks.event.issue_comment.hint', 'New comments on issues'); - // instance-admin sections (InstanceAdminLayout SECTIONS) - t('instanceAdmin.section.general', 'General'); - t('instanceAdmin.section.admins', 'Admins'); - t('instanceAdmin.section.workspace', 'Workspaces'); - t('instanceAdmin.section.email', 'Email'); - t('instanceAdmin.section.authentication', 'Authentication'); - t('instanceAdmin.section.ai', 'Artificial intelligence'); - t('instanceAdmin.section.image', 'Images in Devlane'); - t('instanceAdmin.section.integrations', 'Integrations'); + // instance-admin sections (InstanceAdminLayout SECTIONS) — label + description + t('instanceAdmin.section.general.label', 'General'); + t('instanceAdmin.section.general.desc', 'Identify your instances and get key details.'); + t('instanceAdmin.section.admins.label', 'Admins'); + t('instanceAdmin.section.admins.desc', 'Manage instance administrators.'); + t('instanceAdmin.section.workspace.label', 'Workspaces'); + t('instanceAdmin.section.workspace.desc', 'Manage all workspaces on this instance.'); + t('instanceAdmin.section.email.label', 'Email'); + t('instanceAdmin.section.email.desc', 'Configure your SMTP controls.'); + t('instanceAdmin.section.authentication.label', 'Authentication'); + t('instanceAdmin.section.authentication.desc', 'Configure authentication modes.'); + t('instanceAdmin.section.ai.label', 'Artificial intelligence'); + t('instanceAdmin.section.ai.desc', 'Configure your OpenAI creds.'); + t('instanceAdmin.section.image.label', 'Images in Devlane'); + t('instanceAdmin.section.image.desc', 'Allow third-party image libraries.'); + t('instanceAdmin.section.integrations.label', 'Integrations'); + t('instanceAdmin.section.integrations.desc', 'Configure GitHub and other integrations.'); + + // instance-admin breadcrumb (InstanceAdminLayout BREADCRUMB_LABEL) + t('instanceAdmin.breadcrumb.settings', 'Settings'); + t('instanceAdmin.breadcrumb.general', 'General'); + t('instanceAdmin.breadcrumb.admins', 'Admins'); + t('instanceAdmin.breadcrumb.workspace', 'Workspace'); + t('instanceAdmin.breadcrumb.email', 'Email'); + t('instanceAdmin.breadcrumb.authentication', 'Authentication'); + t('instanceAdmin.breadcrumb.ai', 'Artificial Intelligence'); + t('instanceAdmin.breadcrumb.image', 'Image'); + t('instanceAdmin.breadcrumb.integrations', 'Integrations'); // project section switcher (ProjectSectionDropdown / ProjectSectionHeader) t('header.section.issues', 'Work items'); @@ -118,6 +137,119 @@ export function registerDynamicKeys(t: TFunction) { t('header.section.pages', 'Pages'); t('header.section.views', 'Views'); + // project sidebar nav (Sidebar) + t('nav.project.issues', 'Work items'); + t('nav.project.epics', 'Epics'); + t('nav.project.cycles', 'Cycles'); + t('nav.project.modules', 'Modules'); + t('nav.project.views', 'Views'); + t('nav.project.pages', 'Pages'); + t('nav.project.intake', 'Intake'); + + // home widgets (WorkspaceHomePage) + t('home.widget.quicklinks', 'Quicklinks'); + t('home.widget.recents', 'Recents'); + t('home.widget.stickies', 'Your stickies'); + + // notifications tabs (NotificationsPage) + t('notifications.tab.all', 'All'); + t('notifications.tab.mentions', 'Mentions'); + t('notifications.tab.archived', 'Archived'); + + // pages tabs + sort (PagesPage) + t('pages.tab.public', 'Public'); + t('pages.tab.private', 'Private'); + t('pages.tab.archived', 'Archived'); + t('pages.sort.updated_at', 'Date modified'); + t('pages.sort.created_at', 'Date created'); + t('pages.sort.name', 'Name'); + + // saved-view date presets (ProjectSavedViewActiveFilters) + t('views.filter.datePreset.1_week', 'Last 1 week'); + t('views.filter.datePreset.2_weeks', 'Last 2 weeks'); + t('views.filter.datePreset.1_month', 'Last 1 month'); + t('views.filter.datePreset.2_months', 'Last 2 months'); + t('views.filter.datePreset.custom', 'Custom range'); + + // estimate type options (ProjectEstimatesSettings) + t('settings.estimates.typeOption.points', 'Points'); + t('settings.estimates.typeOption.categories', 'Categories'); + + // notification preference rows (NotificationPreferencesPanel) — label + desc + t('settings.notifications.row.property.label', 'Property changes'); + t( + 'settings.notifications.row.property.desc', + "Notify me when work items' properties like assignees, priority, or estimates change.", + ); + t('settings.notifications.row.state.label', 'State change'); + t( + 'settings.notifications.row.state.desc', + 'Notify me when a work item moves to a different state.', + ); + t('settings.notifications.row.completed.label', 'Work item completed'); + t('settings.notifications.row.completed.desc', 'Notify me when a work item is completed.'); + t('settings.notifications.row.comments.label', 'Comments'); + t('settings.notifications.row.comments.desc', 'Notify me when someone comments on a work item.'); + t('settings.notifications.row.mentions.label', 'Mentions'); + t( + 'settings.notifications.row.mentions.desc', + 'Notify me when someone mentions me in a comment or description.', + ); + + // page-editor colour names (ColorDropdown) + t('editor.colorName.gray', 'Gray'); + t('editor.colorName.brown', 'Brown'); + t('editor.colorName.orange', 'Orange'); + t('editor.colorName.yellow', 'Yellow'); + t('editor.colorName.green', 'Green'); + t('editor.colorName.blue', 'Blue'); + t('editor.colorName.purple', 'Purple'); + t('editor.colorName.red', 'Red'); + + // page-editor slash menu (slashCommands ITEMS) — title + subtitle + t('editor.slash.text.title', 'Text'); + t('editor.slash.text.subtitle', 'Plain paragraph'); + t('editor.slash.heading1.title', 'Heading 1'); + t('editor.slash.heading1.subtitle', 'Large section heading'); + t('editor.slash.heading2.title', 'Heading 2'); + t('editor.slash.heading2.subtitle', 'Medium section heading'); + t('editor.slash.heading3.title', 'Heading 3'); + t('editor.slash.heading3.subtitle', 'Small section heading'); + t('editor.slash.bulletList.title', 'Bulleted list'); + t('editor.slash.bulletList.subtitle', 'Unordered list'); + t('editor.slash.numberedList.title', 'Numbered list'); + t('editor.slash.numberedList.subtitle', 'Ordered list'); + t('editor.slash.todoList.title', 'To-do list'); + t('editor.slash.todoList.subtitle', 'Checklist'); + t('editor.slash.quote.title', 'Quote'); + t('editor.slash.quote.subtitle', 'Block quote'); + t('editor.slash.codeBlock.title', 'Code block'); + t('editor.slash.codeBlock.subtitle', 'Formatted code'); + t('editor.slash.table.title', 'Table'); + t('editor.slash.table.subtitle', '3x3 table'); + t('editor.slash.image.title', 'Image'); + t('editor.slash.image.subtitle', 'Embed by URL'); + t('editor.slash.divider.title', 'Divider'); + t('editor.slash.divider.subtitle', 'Horizontal rule'); + + // page-editor toolbar (PageEditorToolbar item.labelKey) + t('editor.toolbar.bold', 'Bold'); + t('editor.toolbar.italic', 'Italic'); + t('editor.toolbar.underline', 'Underline'); + t('editor.toolbar.strikethrough', 'Strikethrough'); + t('editor.toolbar.alignLeft', 'Left align'); + t('editor.toolbar.alignCenter', 'Center align'); + t('editor.toolbar.alignRight', 'Right align'); + t('editor.toolbar.numberedList', 'Numbered list'); + t('editor.toolbar.bulletedList', 'Bulleted list'); + t('editor.toolbar.todoList', 'To-do list'); + t('editor.toolbar.quote', 'Quote'); + t('editor.toolbar.inlineCode', 'Inline code'); + t('editor.toolbar.codeBlock', 'Code block'); + t('editor.toolbar.insertTable', 'Insert table'); + t('editor.toolbar.insertImage', 'Insert image'); + t('editor.toolbar.imageUrlPrompt', 'Image URL'); + // org-size select (constants/workspace.ts) t('workspace.orgSize.selectRange', 'Select a range'); } diff --git a/apps/web/src/i18n/locales/az/translation.json b/apps/web/src/i18n/locales/az/translation.json index eae67e18..95b9bcef 100644 --- a/apps/web/src/i18n/locales/az/translation.json +++ b/apps/web/src/i18n/locales/az/translation.json @@ -543,7 +543,7 @@ "drafts.loadWorkspaceError": "İş sahəsi yüklənə bilmədi.", "drafts.makeCopy": "Nüsxə çıxar", "drafts.moduleCount_one": "{{count}} modul", - "drafts.moduleCount_other": "{{count}} Modul", + "drafts.moduleCount_other": "{{count}} modul", "drafts.moveToIssues": "Məsələlərə köçür", "drafts.noCycle": "Tsikl yoxdur", "drafts.noModule": "Modul yoxdur", @@ -569,13 +569,60 @@ "editor.clearBackground": "Fonu təmizlə", "editor.clearTextColor": "Mətn rəngini təmizlə", "editor.color": "Rəng", + "editor.colorName.blue": "Mavi", + "editor.colorName.brown": "Qəhvəyi", + "editor.colorName.gray": "Boz", + "editor.colorName.green": "Yaşıl", + "editor.colorName.orange": "Narıncı", + "editor.colorName.purple": "Bənövşəyi", + "editor.colorName.red": "Qırmızı", + "editor.colorName.yellow": "Sarı", "editor.iconPicker.title": "İkona seçin", "editor.mention.noMembers": "Üzv tapılmadı", "editor.outline.empty": "Səhifəyə əlavə etdiyiniz başlıqlar burada görünür.", + "editor.slash.bulletList.subtitle": "Nizamsız siyahı", + "editor.slash.bulletList.title": "Markerli siyahı", + "editor.slash.codeBlock.subtitle": "Formatlanmış kod", + "editor.slash.codeBlock.title": "Kod bloku", + "editor.slash.divider.subtitle": "Üfüqi xətt", + "editor.slash.divider.title": "Ayırıcı", + "editor.slash.heading1.subtitle": "Böyük bölmə başlığı", + "editor.slash.heading1.title": "Başlıq 1", + "editor.slash.heading2.subtitle": "Orta bölmə başlığı", + "editor.slash.heading2.title": "Başlıq 2", + "editor.slash.heading3.subtitle": "Kiçik bölmə başlığı", + "editor.slash.heading3.title": "Başlıq 3", + "editor.slash.image.subtitle": "URL ilə əlavə et", + "editor.slash.image.title": "Şəkil", "editor.slash.imagePrompt": "Şəkil URL-i", "editor.slash.noMatch": "Uyğun bloklar yoxdur", + "editor.slash.numberedList.subtitle": "Nizamlı siyahı", + "editor.slash.numberedList.title": "Nömrəli siyahı", + "editor.slash.quote.subtitle": "Sitat bloku", + "editor.slash.quote.title": "Sitat", + "editor.slash.table.subtitle": "3x3 cədvəl", + "editor.slash.table.title": "Cədvəl", + "editor.slash.text.subtitle": "Adi abzas", + "editor.slash.text.title": "Mətn", + "editor.slash.todoList.subtitle": "Yoxlama siyahısı", + "editor.slash.todoList.title": "Görüləcək işlər siyahısı", "editor.textColor": "Mətn rəngi", + "editor.toolbar.alignCenter": "Mərkəzə düzlə", + "editor.toolbar.alignLeft": "Sola düzlə", + "editor.toolbar.alignRight": "Sağa düzlə", + "editor.toolbar.bold": "Qalın", + "editor.toolbar.bulletedList": "Markerli siyahı", + "editor.toolbar.codeBlock": "Kod bloku", "editor.toolbar.imageUrlPrompt": "Şəkil URL-i", + "editor.toolbar.inlineCode": "Sətirdaxili kod", + "editor.toolbar.insertImage": "Şəkil əlavə et", + "editor.toolbar.insertTable": "Cədvəl əlavə et", + "editor.toolbar.italic": "Kursiv", + "editor.toolbar.numberedList": "Nömrəli siyahı", + "editor.toolbar.quote": "Sitat", + "editor.toolbar.strikethrough": "Üstdən xətt", + "editor.toolbar.todoList": "Görüləcək işlər siyahısı", + "editor.toolbar.underline": "Altdan xətt", "editor.typography.heading": "Başlıq {{level}}", "editor.typography.text": "Mətn", "editor.typography.textStyle": "Mətn stili", @@ -743,6 +790,9 @@ "home.stickies.searchButtonAriaLabel": "Yapışqanları axtar", "home.stickies.searchPlaceholder": "Başlıq və ya məzmuna görə axtar", "home.stickies.title": "Yapışqanlarınız", + "home.widget.quicklinks": "Sürətli keçidlər", + "home.widget.recents": "Sonuncular", + "home.widget.stickies": "Yapışqan qeydləriniz", "image.browse": "Gözdən keçir", "image.coverTitle": "Örtük şəklini seçin", "image.dragDrop": "Şəkli bura sürüşdürün və buraxın", @@ -848,7 +898,15 @@ "instanceAdmin.auth.tooltip.invalidCredentials": "OAuth etimadnamələri yoxdur və ya yanlışdır. Düzəltmək və ya söndürmək üçün Konfiqurasiya et bölməsini açın.", "instanceAdmin.auth.tooltip.missingBeforeEnable": "Bu provayderi aktiv etməzdən əvvəl konfiqurasiya səhifəsində OAuth client məlumatlarını əlavə edin.", "instanceAdmin.auth.unchangedIfBlank": "(boş buraxılarsa dəyişməz qalır)", - "instanceAdmin.breadcrumb.settings": "Parametrlər", + "instanceAdmin.breadcrumb.admins": "Adminlər", + "instanceAdmin.breadcrumb.ai": "Süni intellekt", + "instanceAdmin.breadcrumb.authentication": "Autentifikasiya", + "instanceAdmin.breadcrumb.email": "E-poçt", + "instanceAdmin.breadcrumb.general": "Ümumi", + "instanceAdmin.breadcrumb.image": "Şəkil", + "instanceAdmin.breadcrumb.integrations": "İnteqrasiyalar", + "instanceAdmin.breadcrumb.settings": "Tənzimləmələr", + "instanceAdmin.breadcrumb.workspace": "İş sahəsi", "instanceAdmin.createWorkspace": "İş sahəsi yarat", "instanceAdmin.createWorkspace.create": "İş sahəsi yarat", "instanceAdmin.createWorkspace.creating": "Yaradılır…", @@ -947,14 +1005,22 @@ "instanceAdmin.integrations.subtitle": "Üçüncü tərəf tətbiq kimlik məlumatlarını konfiqurasiya edin. İnteqrasiya burada konfiqurasiya edildikdən sonra, iş sahəsi adminləri onu öz iş sahəsi parametrlərindən qoşa bilər.", "instanceAdmin.integrations.title": "Bu instansiyada mövcud inteqrasiyalar", "instanceAdmin.redirectToDevlane": "Devlane-ə yönləndir", - "instanceAdmin.section.admins": "Adminlər", - "instanceAdmin.section.ai": "Süni intellekt", - "instanceAdmin.section.authentication": "Autentifikasiya", - "instanceAdmin.section.email": "E-poçt", - "instanceAdmin.section.general": "Ümumi", - "instanceAdmin.section.image": "Devlane-də şəkillər", - "instanceAdmin.section.integrations": "İnteqrasiyalar", - "instanceAdmin.section.workspace": "İş sahələri", + "instanceAdmin.section.admins.desc": "İnstansiya administratorlarını idarə edin.", + "instanceAdmin.section.admins.label": "Adminlər", + "instanceAdmin.section.ai.desc": "OpenAI etimadnamələrinizi konfiqurasiya edin.", + "instanceAdmin.section.ai.label": "Süni intellekt", + "instanceAdmin.section.authentication.desc": "Autentifikasiya rejimlərini konfiqurasiya edin.", + "instanceAdmin.section.authentication.label": "Autentifikasiya", + "instanceAdmin.section.email.desc": "SMTP tənzimləmələrinizi konfiqurasiya edin.", + "instanceAdmin.section.email.label": "E-poçt", + "instanceAdmin.section.general.desc": "İnstansiyalarınızı müəyyən edin və əsas detalları əldə edin.", + "instanceAdmin.section.general.label": "Ümumi", + "instanceAdmin.section.image.desc": "Üçüncü tərəf şəkil kitabxanalarına icazə verin.", + "instanceAdmin.section.image.label": "Devlane-də şəkillər", + "instanceAdmin.section.integrations.desc": "GitHub və digər inteqrasiyaları konfiqurasiya edin.", + "instanceAdmin.section.integrations.label": "İnteqrasiyalar", + "instanceAdmin.section.workspace.desc": "Bu instansiyadakı bütün iş sahələrini idarə edin.", + "instanceAdmin.section.workspace.label": "İş sahələri", "instanceAdmin.title": "İnstansiya admini", "instanceAdmin.workspaces.create": "İş sahəsi yarat", "instanceAdmin.workspaces.documentTitle": "İş sahələri", @@ -1106,6 +1172,13 @@ "nav.newFolder": "Yeni qovluq", "nav.newWorkItem": "Yeni iş elementi", "nav.openCommandPalette": "Əmr paletini aç", + "nav.project.cycles": "Tsikllər", + "nav.project.epics": "Epiklər", + "nav.project.intake": "Qəbul", + "nav.project.issues": "İş elementləri", + "nav.project.modules": "Modullar", + "nav.project.pages": "Səhifələr", + "nav.project.views": "Görünüşlər", "nav.projects": "Layihələr", "nav.removeFavorite": "Sevimlini sil", "nav.search": "Axtar", @@ -1144,6 +1217,9 @@ "notifications.stateChangedFrom": "buradan", "notifications.stateChangedTo": "buraya", "notifications.subscribed": "{{actor}} {{issueRef}} işini yenilədi", + "notifications.tab.all": "Hamısı", + "notifications.tab.archived": "Arxivlənmiş", + "notifications.tab.mentions": "Qeyd etmələr", "page.addSubPage": "Alt-səhifə əlavə et", "page.archive": "Arxivlə", "page.archived": "Arxivləndi", @@ -1219,6 +1295,12 @@ "pages.public": "İctimai", "pages.quickFilters": "Sürətli filtrlər", "pages.searchPlaceholder": "Səhifələri axtar", + "pages.sort.created_at": "Yaradılma tarixi", + "pages.sort.name": "Ad", + "pages.sort.updated_at": "Dəyişdirilmə tarixi", + "pages.tab.archived": "Arxivlənmiş", + "pages.tab.private": "Şəxsi", + "pages.tab.public": "İctimai", "pages.title": "Başlıq", "pages.unfavorite": "Sevimlilərdən çıxar", "pages.untitled": "Adsız", @@ -1399,6 +1481,8 @@ "settings.estimates.setActiveLabel": "Aktiv qiymətləndirmə sistemi kimi təyin et", "settings.estimates.title": "Qiymətləndirmələr", "settings.estimates.type": "Növ", + "settings.estimates.typeOption.categories": "Kateqoriyalar", + "settings.estimates.typeOption.points": "Xallar", "settings.export.action": "İxrac et", "settings.export.allProjects": "Bütün layihələr", "settings.export.empty": "Hələ ixrac yoxdur", @@ -1487,6 +1571,16 @@ "settings.notifications.inAppAria": "{{label}} tətbiqdaxili", "settings.notifications.project.description": "Bu layihədəki işlər üçün necə xəbərdar edildiyiniz. İş sahəsi və hesab defoltlarını ləğv edir.", "settings.notifications.project.title": "Layihə bildirişləri", + "settings.notifications.row.comments.desc": "Kimsə iş elementinə şərh yazdıqda mənə bildiriş göndər.", + "settings.notifications.row.comments.label": "Şərhlər", + "settings.notifications.row.completed.desc": "İş elementi tamamlandıqda mənə bildiriş göndər.", + "settings.notifications.row.completed.label": "İş elementi tamamlandı", + "settings.notifications.row.mentions.desc": "Kimsə məni şərhdə və ya təsvirdə qeyd etdikdə mənə bildiriş göndər.", + "settings.notifications.row.mentions.label": "Qeyd etmələr", + "settings.notifications.row.property.desc": "İş elementlərinin təyin edilənlər, prioritet və ya qiymətləndirmə kimi xüsusiyyətləri dəyişdikdə mənə bildiriş göndər.", + "settings.notifications.row.property.label": "Xüsusiyyət dəyişiklikləri", + "settings.notifications.row.state.desc": "İş elementi başqa vəziyyətə keçdikdə mənə bildiriş göndər.", + "settings.notifications.row.state.label": "Vəziyyət dəyişikliyi", "settings.notifications.title": "Bildirişlər", "settings.notifications.workspace.description": "Bu iş sahəsindəki iş barədə necə xəbərdar edildiyiniz. Hesab standartlarınızı əvəz edir; layihələr bunu əvəz edə bilər.", "settings.notifications.workspace.title": "İş sahəsi bildirişləri", @@ -1630,7 +1724,7 @@ "settings.webhooks.noSecret": "(gizli açar qaytarılmadı)", "settings.webhooks.pause": "Fasilə ver", "settings.webhooks.resume": "Davam et", - "settings.webhooks.retriesCount_one": "{{count}} yenidən cəhd", + "settings.webhooks.retriesCount_one": "{{count}} təkrar cəhd", "settings.webhooks.retriesCount_other": "{{count}} təkrar cəhd", "settings.webhooks.secretHint": "Bu imzalama sirrini indi kopyalayın; o bir daha göstərilməyəcək. Gələn sorğularda X-Devlane-Signature başlığını yoxlamaq üçün ondan istifadə edin.", "settings.webhooks.status.active": "Aktiv", @@ -1755,6 +1849,11 @@ "views.filter.clearFilter": "{{label}} filtrini təmizlə", "views.filter.createdByLabel": "Yaradan", "views.filter.customRange": "Fərdi · {{after}} → {{before}}", + "views.filter.datePreset.1_month": "Son 1 ay", + "views.filter.datePreset.1_week": "Son 1 həftə", + "views.filter.datePreset.2_months": "Son 2 ay", + "views.filter.datePreset.2_weeks": "Son 2 həftə", + "views.filter.datePreset.custom": "Fərdi aralıq", "views.filter.dueDateLabel": "Son tarix", "views.filter.grouping.active": "Aktiv", "views.filter.grouping.backlog": "Backlog", diff --git a/apps/web/src/i18n/locales/en/translation.json b/apps/web/src/i18n/locales/en/translation.json index 2f089869..b52967e6 100644 --- a/apps/web/src/i18n/locales/en/translation.json +++ b/apps/web/src/i18n/locales/en/translation.json @@ -385,12 +385,12 @@ "common.state": "State", "common.subWorkItems": "Sub-work items", "common.time.daysAgo_one": "{{count}} day ago", - "common.time.daysAgo_other": "{{count}} day ago", + "common.time.daysAgo_other": "{{count}} days ago", "common.time.hoursAgo_one": "{{count}} hour ago", - "common.time.hoursAgo_other": "{{count}} hour ago", + "common.time.hoursAgo_other": "{{count}} hours ago", "common.time.justNow": "just now", "common.time.minutesAgo_one": "{{count}} minute ago", - "common.time.minutesAgo_other": "{{count}} minute ago", + "common.time.minutesAgo_other": "{{count}} minutes ago", "common.title": "Title", "common.titleRequired": "Title is required.", "common.today": "Today", @@ -542,7 +542,7 @@ "drafts.loadingDrafts": "Loading drafts…", "drafts.loadWorkspaceError": "Could not load workspace.", "drafts.makeCopy": "Make a copy", - "drafts.moduleCount_one": "{{count}} Modules", + "drafts.moduleCount_one": "{{count}} Module", "drafts.moduleCount_other": "{{count}} Modules", "drafts.moveToIssues": "Move to issues", "drafts.noCycle": "No cycle", @@ -569,13 +569,60 @@ "editor.clearBackground": "Clear background", "editor.clearTextColor": "Clear text color", "editor.color": "Color", + "editor.colorName.blue": "Blue", + "editor.colorName.brown": "Brown", + "editor.colorName.gray": "Gray", + "editor.colorName.green": "Green", + "editor.colorName.orange": "Orange", + "editor.colorName.purple": "Purple", + "editor.colorName.red": "Red", + "editor.colorName.yellow": "Yellow", "editor.iconPicker.title": "Pick an icon", "editor.mention.noMembers": "No members found", "editor.outline.empty": "Headings you add to the page show up here.", + "editor.slash.bulletList.subtitle": "Unordered list", + "editor.slash.bulletList.title": "Bulleted list", + "editor.slash.codeBlock.subtitle": "Formatted code", + "editor.slash.codeBlock.title": "Code block", + "editor.slash.divider.subtitle": "Horizontal rule", + "editor.slash.divider.title": "Divider", + "editor.slash.heading1.subtitle": "Large section heading", + "editor.slash.heading1.title": "Heading 1", + "editor.slash.heading2.subtitle": "Medium section heading", + "editor.slash.heading2.title": "Heading 2", + "editor.slash.heading3.subtitle": "Small section heading", + "editor.slash.heading3.title": "Heading 3", + "editor.slash.image.subtitle": "Embed by URL", + "editor.slash.image.title": "Image", "editor.slash.imagePrompt": "Image URL", "editor.slash.noMatch": "No matching blocks", + "editor.slash.numberedList.subtitle": "Ordered list", + "editor.slash.numberedList.title": "Numbered list", + "editor.slash.quote.subtitle": "Block quote", + "editor.slash.quote.title": "Quote", + "editor.slash.table.subtitle": "3x3 table", + "editor.slash.table.title": "Table", + "editor.slash.text.subtitle": "Plain paragraph", + "editor.slash.text.title": "Text", + "editor.slash.todoList.subtitle": "Checklist", + "editor.slash.todoList.title": "To-do list", "editor.textColor": "Text color", + "editor.toolbar.alignCenter": "Center align", + "editor.toolbar.alignLeft": "Left align", + "editor.toolbar.alignRight": "Right align", + "editor.toolbar.bold": "Bold", + "editor.toolbar.bulletedList": "Bulleted list", + "editor.toolbar.codeBlock": "Code block", "editor.toolbar.imageUrlPrompt": "Image URL", + "editor.toolbar.inlineCode": "Inline code", + "editor.toolbar.insertImage": "Insert image", + "editor.toolbar.insertTable": "Insert table", + "editor.toolbar.italic": "Italic", + "editor.toolbar.numberedList": "Numbered list", + "editor.toolbar.quote": "Quote", + "editor.toolbar.strikethrough": "Strikethrough", + "editor.toolbar.todoList": "To-do list", + "editor.toolbar.underline": "Underline", "editor.typography.heading": "Heading {{level}}", "editor.typography.text": "Text", "editor.typography.textStyle": "Text style", @@ -743,6 +790,9 @@ "home.stickies.searchButtonAriaLabel": "Search stickies", "home.stickies.searchPlaceholder": "Search by title or content", "home.stickies.title": "Your stickies", + "home.widget.quicklinks": "Quicklinks", + "home.widget.recents": "Recents", + "home.widget.stickies": "Your stickies", "image.browse": "Browse", "image.coverTitle": "Select cover image", "image.dragDrop": "Drag & drop image here", @@ -848,7 +898,15 @@ "instanceAdmin.auth.tooltip.invalidCredentials": "OAuth credentials are missing or invalid. Open Configure to fix or turn this off.", "instanceAdmin.auth.tooltip.missingBeforeEnable": "Add OAuth client credentials on the configuration page before enabling this provider.", "instanceAdmin.auth.unchangedIfBlank": "(unchanged if left blank)", + "instanceAdmin.breadcrumb.admins": "Admins", + "instanceAdmin.breadcrumb.ai": "Artificial Intelligence", + "instanceAdmin.breadcrumb.authentication": "Authentication", + "instanceAdmin.breadcrumb.email": "Email", + "instanceAdmin.breadcrumb.general": "General", + "instanceAdmin.breadcrumb.image": "Image", + "instanceAdmin.breadcrumb.integrations": "Integrations", "instanceAdmin.breadcrumb.settings": "Settings", + "instanceAdmin.breadcrumb.workspace": "Workspace", "instanceAdmin.createWorkspace": "Create workspace", "instanceAdmin.createWorkspace.create": "Create workspace", "instanceAdmin.createWorkspace.creating": "Creating…", @@ -947,14 +1005,22 @@ "instanceAdmin.integrations.subtitle": "Configure third-party app credentials. Once an integration is configured here, workspace admins can connect it from their workspace settings.", "instanceAdmin.integrations.title": "Integrations available on this instance", "instanceAdmin.redirectToDevlane": "Redirect to Devlane", - "instanceAdmin.section.admins": "Admins", - "instanceAdmin.section.ai": "Artificial intelligence", - "instanceAdmin.section.authentication": "Authentication", - "instanceAdmin.section.email": "Email", - "instanceAdmin.section.general": "General", - "instanceAdmin.section.image": "Images in Devlane", - "instanceAdmin.section.integrations": "Integrations", - "instanceAdmin.section.workspace": "Workspaces", + "instanceAdmin.section.admins.desc": "Manage instance administrators.", + "instanceAdmin.section.admins.label": "Admins", + "instanceAdmin.section.ai.desc": "Configure your OpenAI creds.", + "instanceAdmin.section.ai.label": "Artificial intelligence", + "instanceAdmin.section.authentication.desc": "Configure authentication modes.", + "instanceAdmin.section.authentication.label": "Authentication", + "instanceAdmin.section.email.desc": "Configure your SMTP controls.", + "instanceAdmin.section.email.label": "Email", + "instanceAdmin.section.general.desc": "Identify your instances and get key details.", + "instanceAdmin.section.general.label": "General", + "instanceAdmin.section.image.desc": "Allow third-party image libraries.", + "instanceAdmin.section.image.label": "Images in Devlane", + "instanceAdmin.section.integrations.desc": "Configure GitHub and other integrations.", + "instanceAdmin.section.integrations.label": "Integrations", + "instanceAdmin.section.workspace.desc": "Manage all workspaces on this instance.", + "instanceAdmin.section.workspace.label": "Workspaces", "instanceAdmin.title": "Instance admin", "instanceAdmin.workspaces.create": "Create workspace", "instanceAdmin.workspaces.documentTitle": "Workspaces", @@ -1106,6 +1172,13 @@ "nav.newFolder": "New folder", "nav.newWorkItem": "New work item", "nav.openCommandPalette": "Open command palette", + "nav.project.cycles": "Cycles", + "nav.project.epics": "Epics", + "nav.project.intake": "Intake", + "nav.project.issues": "Work items", + "nav.project.modules": "Modules", + "nav.project.pages": "Pages", + "nav.project.views": "Views", "nav.projects": "Projects", "nav.removeFavorite": "Remove favorite", "nav.search": "Search", @@ -1144,6 +1217,9 @@ "notifications.stateChangedFrom": "from", "notifications.stateChangedTo": "to", "notifications.subscribed": "{{actor}} updated {{issueRef}}", + "notifications.tab.all": "All", + "notifications.tab.archived": "Archived", + "notifications.tab.mentions": "Mentions", "page.addSubPage": "Add sub-page", "page.archive": "Archive", "page.archived": "Archived", @@ -1219,6 +1295,12 @@ "pages.public": "Public", "pages.quickFilters": "Quick filters", "pages.searchPlaceholder": "Search pages", + "pages.sort.created_at": "Date created", + "pages.sort.name": "Name", + "pages.sort.updated_at": "Date modified", + "pages.tab.archived": "Archived", + "pages.tab.private": "Private", + "pages.tab.public": "Public", "pages.title": "Title", "pages.unfavorite": "Unfavorite", "pages.untitled": "Untitled", @@ -1399,6 +1481,8 @@ "settings.estimates.setActiveLabel": "Set as the active estimate system", "settings.estimates.title": "Estimates", "settings.estimates.type": "Type", + "settings.estimates.typeOption.categories": "Categories", + "settings.estimates.typeOption.points": "Points", "settings.export.action": "Export", "settings.export.allProjects": "All projects", "settings.export.empty": "No exports yet", @@ -1487,6 +1571,16 @@ "settings.notifications.inAppAria": "{{label}} in-app", "settings.notifications.project.description": "How you're notified for work in this project. Overrides your workspace and account defaults.", "settings.notifications.project.title": "Project notifications", + "settings.notifications.row.comments.desc": "Notify me when someone comments on a work item.", + "settings.notifications.row.comments.label": "Comments", + "settings.notifications.row.completed.desc": "Notify me when a work item is completed.", + "settings.notifications.row.completed.label": "Work item completed", + "settings.notifications.row.mentions.desc": "Notify me when someone mentions me in a comment or description.", + "settings.notifications.row.mentions.label": "Mentions", + "settings.notifications.row.property.desc": "Notify me when work items' properties like assignees, priority, or estimates change.", + "settings.notifications.row.property.label": "Property changes", + "settings.notifications.row.state.desc": "Notify me when a work item moves to a different state.", + "settings.notifications.row.state.label": "State change", "settings.notifications.title": "Notifications", "settings.notifications.workspace.description": "How you're notified for work in this workspace. Overrides your account defaults; projects can override this.", "settings.notifications.workspace.title": "Workspace notifications", @@ -1630,7 +1724,7 @@ "settings.webhooks.noSecret": "(no secret returned)", "settings.webhooks.pause": "Pause", "settings.webhooks.resume": "Resume", - "settings.webhooks.retriesCount_one": "{{count}} retries", + "settings.webhooks.retriesCount_one": "{{count}} retry", "settings.webhooks.retriesCount_other": "{{count}} retries", "settings.webhooks.secretHint": "Copy this signing secret now; it will not be shown again. Use it to verify the X-Devlane-Signature header on incoming requests.", "settings.webhooks.status.active": "Active", @@ -1755,6 +1849,11 @@ "views.filter.clearFilter": "Clear {{label}} filter", "views.filter.createdByLabel": "Created by", "views.filter.customRange": "Custom · {{after}} → {{before}}", + "views.filter.datePreset.1_month": "Last 1 month", + "views.filter.datePreset.1_week": "Last 1 week", + "views.filter.datePreset.2_months": "Last 2 months", + "views.filter.datePreset.2_weeks": "Last 2 weeks", + "views.filter.datePreset.custom": "Custom range", "views.filter.dueDateLabel": "Due date", "views.filter.grouping.active": "Active", "views.filter.grouping.backlog": "Backlog",