diff --git a/packages/i18n/src/constants/language.ts b/packages/i18n/src/constants/language.ts index d3d3a887a34..4969178a598 100644 --- a/packages/i18n/src/constants/language.ts +++ b/packages/i18n/src/constants/language.ts @@ -24,4 +24,13 @@ export const SUPPORTED_LANGUAGES: ILanguageOption[] = [ { label: "Türkçe", value: "tr-TR" }, ]; +/** + * Enum for translation file names + * These are the JSON files that contain translations each category + */ +export enum ETranslationFiles { + TRANSLATIONS = "translations", + ACCESSIBILITY = "accessibility", +} + export const LANGUAGE_STORAGE_KEY = "userLanguage"; diff --git a/packages/i18n/src/locales/cs/accessibility.json b/packages/i18n/src/locales/cs/accessibility.json new file mode 100644 index 00000000000..4a715f75be1 --- /dev/null +++ b/packages/i18n/src/locales/cs/accessibility.json @@ -0,0 +1,27 @@ +{ + "aria_labels": { + "projects_sidebar": { + "workspace_logo": "Logo pracovního prostoru", + "open_workspace_switcher": "Otevřít přepínač pracovního prostoru", + "open_user_menu": "Otevřít uživatelské menu", + "open_command_palette": "Otevřít paletu příkazů", + "open_extended_sidebar": "Otevřít rozšířený postranní panel", + "close_extended_sidebar": "Zavřít rozšířený postranní panel", + "create_favorites_folder": "Vytvořit složku oblíbených", + "open_folder": "Otevřít složku", + "close_folder": "Zavřít složku", + "open_favorites_menu": "Otevřít menu oblíbených", + "close_favorites_menu": "Zavřít menu oblíbených", + "enter_folder_name": "Zadejte název složky", + "create_new_project": "Vytvořit nový projekt", + "open_projects_menu": "Otevřít menu projektů", + "close_projects_menu": "Zavřít menu projektů", + "toggle_quick_actions_menu": "Přepnout menu rychlých akcí", + "open_project_menu": "Otevřít menu projektu", + "close_project_menu": "Zavřít menu projektu", + "collapse_sidebar": "Sbalit postranní panel", + "expand_sidebar": "Rozbalit postranní panel", + "edition_badge": "Otevřít modal placených plánů" + } + } +} \ No newline at end of file diff --git a/packages/i18n/src/locales/de/accessibility.json b/packages/i18n/src/locales/de/accessibility.json new file mode 100644 index 00000000000..0faf0091681 --- /dev/null +++ b/packages/i18n/src/locales/de/accessibility.json @@ -0,0 +1,27 @@ +{ + "aria_labels": { + "projects_sidebar": { + "workspace_logo": "Arbeitsbereich-Logo", + "open_workspace_switcher": "Arbeitsbereich-Umschalter öffnen", + "open_user_menu": "Benutzermenü öffnen", + "open_command_palette": "Befehlspalette öffnen", + "open_extended_sidebar": "Erweiterte Seitenleiste öffnen", + "close_extended_sidebar": "Erweiterte Seitenleiste schließen", + "create_favorites_folder": "Favoriten-Ordner erstellen", + "open_folder": "Ordner öffnen", + "close_folder": "Ordner schließen", + "open_favorites_menu": "Favoriten-Menü öffnen", + "close_favorites_menu": "Favoriten-Menü schließen", + "enter_folder_name": "Ordnername eingeben", + "create_new_project": "Neues Projekt erstellen", + "open_projects_menu": "Projekt-Menü öffnen", + "close_projects_menu": "Projekt-Menü schließen", + "toggle_quick_actions_menu": "Schnellaktionen-Menü umschalten", + "open_project_menu": "Projekt-Menü öffnen", + "close_project_menu": "Projekt-Menü schließen", + "collapse_sidebar": "Seitenleiste einklappen", + "expand_sidebar": "Seitenleiste ausklappen", + "edition_badge": "Modal für kostenpflichtige Pläne öffnen" + } + } +} \ No newline at end of file diff --git a/packages/i18n/src/locales/en/accessibility.json b/packages/i18n/src/locales/en/accessibility.json new file mode 100644 index 00000000000..35759d26627 --- /dev/null +++ b/packages/i18n/src/locales/en/accessibility.json @@ -0,0 +1,27 @@ +{ + "aria_labels": { + "projects_sidebar": { + "workspace_logo": "Workspace logo", + "open_workspace_switcher": "Open workspace switcher", + "open_user_menu": "Open user menu", + "open_command_palette": "Open command palette", + "open_extended_sidebar": "Open extended sidebar", + "close_extended_sidebar": "Close extended sidebar", + "create_favorites_folder": "Create favorites folder", + "open_folder": "Open folder", + "close_folder": "Close folder", + "open_favorites_menu": "Open favorites menu", + "close_favorites_menu": "Close favorites menu", + "enter_folder_name": "Enter folder name", + "create_new_project": "Create new project", + "open_projects_menu": "Open projects menu", + "close_projects_menu": "Close projects menu", + "toggle_quick_actions_menu": "Toggle quick actions menu", + "open_project_menu": "Open project menu", + "close_project_menu": "Close project menu", + "collapse_sidebar": "Collapse sidebar", + "expand_sidebar": "Expand sidebar", + "edition_badge": "Open paid plans' modal" + } + } +} \ No newline at end of file diff --git a/packages/i18n/src/locales/en/translations.json b/packages/i18n/src/locales/en/translations.json index c959108e0a1..ead40fd1e53 100644 --- a/packages/i18n/src/locales/en/translations.json +++ b/packages/i18n/src/locales/en/translations.json @@ -2296,4 +2296,4 @@ "previously_edited_by": "Previously edited by", "edited_by": "Edited by" } -} +} \ No newline at end of file diff --git a/packages/i18n/src/locales/es/accessibility.json b/packages/i18n/src/locales/es/accessibility.json new file mode 100644 index 00000000000..41bf0b777d0 --- /dev/null +++ b/packages/i18n/src/locales/es/accessibility.json @@ -0,0 +1,27 @@ +{ + "aria_labels": { + "projects_sidebar": { + "workspace_logo": "Logo del espacio de trabajo", + "open_workspace_switcher": "Abrir cambiador de espacio de trabajo", + "open_user_menu": "Abrir menú de usuario", + "open_command_palette": "Abrir paleta de comandos", + "open_extended_sidebar": "Abrir barra lateral extendida", + "close_extended_sidebar": "Cerrar barra lateral extendida", + "create_favorites_folder": "Crear carpeta de favoritos", + "open_folder": "Abrir carpeta", + "close_folder": "Cerrar carpeta", + "open_favorites_menu": "Abrir menú de favoritos", + "close_favorites_menu": "Cerrar menú de favoritos", + "enter_folder_name": "Ingresar nombre de carpeta", + "create_new_project": "Crear nuevo proyecto", + "open_projects_menu": "Abrir menú de proyectos", + "close_projects_menu": "Cerrar menú de proyectos", + "toggle_quick_actions_menu": "Alternar menú de acciones rápidas", + "open_project_menu": "Abrir menú de proyecto", + "close_project_menu": "Cerrar menú de proyecto", + "collapse_sidebar": "Colapsar barra lateral", + "expand_sidebar": "Expandir barra lateral", + "edition_badge": "Abrir modal de planes de pago" + } + } +} \ No newline at end of file diff --git a/packages/i18n/src/locales/fr/accessibility.json b/packages/i18n/src/locales/fr/accessibility.json new file mode 100644 index 00000000000..ba42a4f4183 --- /dev/null +++ b/packages/i18n/src/locales/fr/accessibility.json @@ -0,0 +1,27 @@ +{ + "aria_labels": { + "projects_sidebar": { + "workspace_logo": "Logo de l'espace de travail", + "open_workspace_switcher": "Ouvrir le sélecteur d'espace de travail", + "open_user_menu": "Ouvrir le menu utilisateur", + "open_command_palette": "Ouvrir la palette de commandes", + "open_extended_sidebar": "Ouvrir la barre latérale étendue", + "close_extended_sidebar": "Fermer la barre latérale étendue", + "create_favorites_folder": "Créer un dossier de favoris", + "open_folder": "Ouvrir le dossier", + "close_folder": "Fermer le dossier", + "open_favorites_menu": "Ouvrir le menu des favoris", + "close_favorites_menu": "Fermer le menu des favoris", + "enter_folder_name": "Saisir le nom du dossier", + "create_new_project": "Créer un nouveau projet", + "open_projects_menu": "Ouvrir le menu des projets", + "close_projects_menu": "Fermer le menu des projets", + "toggle_quick_actions_menu": "Basculer le menu d'actions rapides", + "open_project_menu": "Ouvrir le menu du projet", + "close_project_menu": "Fermer le menu du projet", + "collapse_sidebar": "Réduire la barre latérale", + "expand_sidebar": "Étendre la barre latérale", + "edition_badge": "Ouvrir le modal des plans payants" + } + } +} \ No newline at end of file diff --git a/packages/i18n/src/locales/id/accessibility.json b/packages/i18n/src/locales/id/accessibility.json new file mode 100644 index 00000000000..2aca032cc11 --- /dev/null +++ b/packages/i18n/src/locales/id/accessibility.json @@ -0,0 +1,27 @@ +{ + "aria_labels": { + "projects_sidebar": { + "workspace_logo": "Logo ruang kerja", + "open_workspace_switcher": "Buka penukar ruang kerja", + "open_user_menu": "Buka menu pengguna", + "open_command_palette": "Buka palet perintah", + "open_extended_sidebar": "Buka sidebar diperluas", + "close_extended_sidebar": "Tutup sidebar diperluas", + "create_favorites_folder": "Buat folder favorit", + "open_folder": "Buka folder", + "close_folder": "Tutup folder", + "open_favorites_menu": "Buka menu favorit", + "close_favorites_menu": "Tutup menu favorit", + "enter_folder_name": "Masukkan nama folder", + "create_new_project": "Buat proyek baru", + "open_projects_menu": "Buka menu proyek", + "close_projects_menu": "Tutup menu proyek", + "toggle_quick_actions_menu": "Alihkan menu tindakan cepat", + "open_project_menu": "Buka menu proyek", + "close_project_menu": "Tutup menu proyek", + "collapse_sidebar": "Tutup sidebar", + "expand_sidebar": "Perluas sidebar", + "edition_badge": "Buka modal paket berbayar" + } + } +} \ No newline at end of file diff --git a/packages/i18n/src/locales/it/accessibility.json b/packages/i18n/src/locales/it/accessibility.json new file mode 100644 index 00000000000..8f22d3b8ea4 --- /dev/null +++ b/packages/i18n/src/locales/it/accessibility.json @@ -0,0 +1,27 @@ +{ + "aria_labels": { + "projects_sidebar": { + "workspace_logo": "Logo dell'area di lavoro", + "open_workspace_switcher": "Apri selettore area di lavoro", + "open_user_menu": "Apri menu utente", + "open_command_palette": "Apri tavolozza comandi", + "open_extended_sidebar": "Apri barra laterale estesa", + "close_extended_sidebar": "Chiudi barra laterale estesa", + "create_favorites_folder": "Crea cartella preferiti", + "open_folder": "Apri cartella", + "close_folder": "Chiudi cartella", + "open_favorites_menu": "Apri menu preferiti", + "close_favorites_menu": "Chiudi menu preferiti", + "enter_folder_name": "Inserisci nome cartella", + "create_new_project": "Crea nuovo progetto", + "open_projects_menu": "Apri menu progetti", + "close_projects_menu": "Chiudi menu progetti", + "toggle_quick_actions_menu": "Attiva/disattiva menu azioni rapide", + "open_project_menu": "Apri menu progetto", + "close_project_menu": "Chiudi menu progetto", + "collapse_sidebar": "Comprimi barra laterale", + "expand_sidebar": "Espandi barra laterale", + "edition_badge": "Apri modal piani a pagamento" + } + } +} \ No newline at end of file diff --git a/packages/i18n/src/locales/ja/accessibility.json b/packages/i18n/src/locales/ja/accessibility.json new file mode 100644 index 00000000000..a598c435a9a --- /dev/null +++ b/packages/i18n/src/locales/ja/accessibility.json @@ -0,0 +1,27 @@ +{ + "aria_labels": { + "projects_sidebar": { + "workspace_logo": "ワークスペースロゴ", + "open_workspace_switcher": "ワークスペーススイッチャーを開く", + "open_user_menu": "ユーザーメニューを開く", + "open_command_palette": "コマンドパレットを開く", + "open_extended_sidebar": "拡張サイドバーを開く", + "close_extended_sidebar": "拡張サイドバーを閉じる", + "create_favorites_folder": "お気に入りフォルダを作成", + "open_folder": "フォルダを開く", + "close_folder": "フォルダを閉じる", + "open_favorites_menu": "お気に入りメニューを開く", + "close_favorites_menu": "お気に入りメニューを閉じる", + "enter_folder_name": "フォルダ名を入力", + "create_new_project": "新しいプロジェクトを作成", + "open_projects_menu": "プロジェクトメニューを開く", + "close_projects_menu": "プロジェクトメニューを閉じる", + "toggle_quick_actions_menu": "クイックアクションメニューの切り替え", + "open_project_menu": "プロジェクトメニューを開く", + "close_project_menu": "プロジェクトメニューを閉じる", + "collapse_sidebar": "サイドバーを折りたたむ", + "expand_sidebar": "サイドバーを展開", + "edition_badge": "有料プランのモーダルを開く" + } + } +} \ No newline at end of file diff --git a/packages/i18n/src/locales/ko/accessibility.json b/packages/i18n/src/locales/ko/accessibility.json new file mode 100644 index 00000000000..491b8c35c6a --- /dev/null +++ b/packages/i18n/src/locales/ko/accessibility.json @@ -0,0 +1,27 @@ +{ + "aria_labels": { + "projects_sidebar": { + "workspace_logo": "워크스페이스 로고", + "open_workspace_switcher": "워크스페이스 전환기 열기", + "open_user_menu": "사용자 메뉴 열기", + "open_command_palette": "명령 팔레트 열기", + "open_extended_sidebar": "확장된 사이드바 열기", + "close_extended_sidebar": "확장된 사이드바 닫기", + "create_favorites_folder": "즐겨찾기 폴더 생성", + "open_folder": "폴더 열기", + "close_folder": "폴더 닫기", + "open_favorites_menu": "즐겨찾기 메뉴 열기", + "close_favorites_menu": "즐겨찾기 메뉴 닫기", + "enter_folder_name": "폴더 이름 입력", + "create_new_project": "새 프로젝트 생성", + "open_projects_menu": "프로젝트 메뉴 열기", + "close_projects_menu": "프로젝트 메뉴 닫기", + "toggle_quick_actions_menu": "빠른 작업 메뉴 토글", + "open_project_menu": "프로젝트 메뉴 열기", + "close_project_menu": "프로젝트 메뉴 닫기", + "collapse_sidebar": "사이드바 축소", + "expand_sidebar": "사이드바 확장", + "edition_badge": "유료 플랜 모달 열기" + } + } +} \ No newline at end of file diff --git a/packages/i18n/src/locales/pl/accessibility.json b/packages/i18n/src/locales/pl/accessibility.json new file mode 100644 index 00000000000..5ff936d47f2 --- /dev/null +++ b/packages/i18n/src/locales/pl/accessibility.json @@ -0,0 +1,27 @@ +{ + "aria_labels": { + "projects_sidebar": { + "workspace_logo": "Logo obszaru roboczego", + "open_workspace_switcher": "Otwórz przełącznik obszaru roboczego", + "open_user_menu": "Otwórz menu użytkownika", + "open_command_palette": "Otwórz paletę poleceń", + "open_extended_sidebar": "Otwórz rozszerzoną pasek boczny", + "close_extended_sidebar": "Zamknij rozszerzoną pasek boczny", + "create_favorites_folder": "Utwórz folder ulubionych", + "open_folder": "Otwórz folder", + "close_folder": "Zamknij folder", + "open_favorites_menu": "Otwórz menu ulubionych", + "close_favorites_menu": "Zamknij menu ulubionych", + "enter_folder_name": "Wprowadź nazwę folderu", + "create_new_project": "Utwórz nowy projekt", + "open_projects_menu": "Otwórz menu projektów", + "close_projects_menu": "Zamknij menu projektów", + "toggle_quick_actions_menu": "Przełącz menu szybkich akcji", + "open_project_menu": "Otwórz menu projektu", + "close_project_menu": "Zamknij menu projektu", + "collapse_sidebar": "Zwiń pasek boczny", + "expand_sidebar": "Rozwiń pasek boczny", + "edition_badge": "Otwórz modal płatnych planów" + } + } +} \ No newline at end of file diff --git a/packages/i18n/src/locales/pt-BR/accessibility.json b/packages/i18n/src/locales/pt-BR/accessibility.json new file mode 100644 index 00000000000..333b55a7fbc --- /dev/null +++ b/packages/i18n/src/locales/pt-BR/accessibility.json @@ -0,0 +1,27 @@ +{ + "aria_labels": { + "projects_sidebar": { + "workspace_logo": "Logo do espaço de trabalho", + "open_workspace_switcher": "Abrir seletor de espaço de trabalho", + "open_user_menu": "Abrir menu do usuário", + "open_command_palette": "Abrir paleta de comandos", + "open_extended_sidebar": "Abrir barra lateral estendida", + "close_extended_sidebar": "Fechar barra lateral estendida", + "create_favorites_folder": "Criar pasta de favoritos", + "open_folder": "Abrir pasta", + "close_folder": "Fechar pasta", + "open_favorites_menu": "Abrir menu de favoritos", + "close_favorites_menu": "Fechar menu de favoritos", + "enter_folder_name": "Digite o nome da pasta", + "create_new_project": "Criar novo projeto", + "open_projects_menu": "Abrir menu de projetos", + "close_projects_menu": "Fechar menu de projetos", + "toggle_quick_actions_menu": "Alternar menu de ações rápidas", + "open_project_menu": "Abrir menu do projeto", + "close_project_menu": "Fechar menu do projeto", + "collapse_sidebar": "Recolher barra lateral", + "expand_sidebar": "Expandir barra lateral", + "edition_badge": "Abrir modal de planos pagos" + } + } +} \ No newline at end of file diff --git a/packages/i18n/src/locales/ro/accessibility.json b/packages/i18n/src/locales/ro/accessibility.json new file mode 100644 index 00000000000..1a201a48c8a --- /dev/null +++ b/packages/i18n/src/locales/ro/accessibility.json @@ -0,0 +1,27 @@ +{ + "aria_labels": { + "projects_sidebar": { + "workspace_logo": "Logo spațiu de lucru", + "open_workspace_switcher": "Deschide comutator spațiu de lucru", + "open_user_menu": "Deschide meniul utilizatorului", + "open_command_palette": "Deschide paleta de comenzi", + "open_extended_sidebar": "Deschide bara laterală extinsă", + "close_extended_sidebar": "Închide bara laterală extinsă", + "create_favorites_folder": "Creează folder de favorite", + "open_folder": "Deschide folderul", + "close_folder": "Închide folderul", + "open_favorites_menu": "Deschide meniul de favorite", + "close_favorites_menu": "Închide meniul de favorite", + "enter_folder_name": "Introduceți numele folderului", + "create_new_project": "Creează proiect nou", + "open_projects_menu": "Deschide meniul de proiecte", + "close_projects_menu": "Închide meniul de proiecte", + "toggle_quick_actions_menu": "Comută meniul de acțiuni rapide", + "open_project_menu": "Deschide meniul proiectului", + "close_project_menu": "Închide meniul proiectului", + "collapse_sidebar": "Restrânge bara laterală", + "expand_sidebar": "Extinde bara laterală", + "edition_badge": "Deschide modalul planurilor plătite" + } + } +} \ No newline at end of file diff --git a/packages/i18n/src/locales/ru/accessibility.json b/packages/i18n/src/locales/ru/accessibility.json new file mode 100644 index 00000000000..ebec8dc2f86 --- /dev/null +++ b/packages/i18n/src/locales/ru/accessibility.json @@ -0,0 +1,27 @@ +{ + "aria_labels": { + "projects_sidebar": { + "workspace_logo": "Логотип рабочей области", + "open_workspace_switcher": "Открыть переключатель рабочей области", + "open_user_menu": "Открыть пользовательское меню", + "open_command_palette": "Открыть палитру команд", + "open_extended_sidebar": "Открыть расширенную боковую панель", + "close_extended_sidebar": "Закрыть расширенную боковую панель", + "create_favorites_folder": "Создать папку избранного", + "open_folder": "Открыть папку", + "close_folder": "Закрыть папку", + "open_favorites_menu": "Открыть меню избранного", + "close_favorites_menu": "Закрыть меню избранного", + "enter_folder_name": "Введите имя папки", + "create_new_project": "Создать новый проект", + "open_projects_menu": "Открыть меню проектов", + "close_projects_menu": "Закрыть меню проектов", + "toggle_quick_actions_menu": "Переключить меню быстрых действий", + "open_project_menu": "Открыть меню проекта", + "close_project_menu": "Закрыть меню проекта", + "collapse_sidebar": "Свернуть боковую панель", + "expand_sidebar": "Развернуть боковую панель", + "edition_badge": "Открыть модал платных планов" + } + } +} \ No newline at end of file diff --git a/packages/i18n/src/locales/sk/accessibility.json b/packages/i18n/src/locales/sk/accessibility.json new file mode 100644 index 00000000000..59a309f6032 --- /dev/null +++ b/packages/i18n/src/locales/sk/accessibility.json @@ -0,0 +1,27 @@ +{ + "aria_labels": { + "projects_sidebar": { + "workspace_logo": "Logo pracovného priestoru", + "open_workspace_switcher": "Otvoriť prepínač pracovného priestoru", + "open_user_menu": "Otvoriť používateľské menu", + "open_command_palette": "Otvoriť paletu príkazov", + "open_extended_sidebar": "Otvoriť rozšírený bočný panel", + "close_extended_sidebar": "Zavrieť rozšírený bočný panel", + "create_favorites_folder": "Vytvoriť priečinok obľúbených", + "open_folder": "Otvoriť priečinok", + "close_folder": "Zavrieť priečinok", + "open_favorites_menu": "Otvoriť menu obľúbených", + "close_favorites_menu": "Zavrieť menu obľúbených", + "enter_folder_name": "Zadajte názov priečinka", + "create_new_project": "Vytvoriť nový projekt", + "open_projects_menu": "Otvoriť menu projektov", + "close_projects_menu": "Zavrieť menu projektov", + "toggle_quick_actions_menu": "Prepnúť menu rýchlych akcií", + "open_project_menu": "Otvoriť menu projektu", + "close_project_menu": "Zavrieť menu projektu", + "collapse_sidebar": "Zbaliť bočný panel", + "expand_sidebar": "Rozbaliť bočný panel", + "edition_badge": "Otvoriť modal platených plánov" + } + } +} \ No newline at end of file diff --git a/packages/i18n/src/locales/tr-TR/accessibility.json b/packages/i18n/src/locales/tr-TR/accessibility.json new file mode 100644 index 00000000000..35b8f340e9c --- /dev/null +++ b/packages/i18n/src/locales/tr-TR/accessibility.json @@ -0,0 +1,27 @@ +{ + "aria_labels": { + "projects_sidebar": { + "workspace_logo": "Çalışma alanı logosu", + "open_workspace_switcher": "Çalışma alanı değiştiricisini aç", + "open_user_menu": "Kullanıcı menüsünü aç", + "open_command_palette": "Komut paletini aç", + "open_extended_sidebar": "Genişletilmiş kenar çubuğunu aç", + "close_extended_sidebar": "Genişletilmiş kenar çubuğunu kapat", + "create_favorites_folder": "Favoriler klasörü oluştur", + "open_folder": "Klasörü aç", + "close_folder": "Klasörü kapat", + "open_favorites_menu": "Favoriler menüsünü aç", + "close_favorites_menu": "Favoriler menüsünü kapat", + "enter_folder_name": "Klasör adını girin", + "create_new_project": "Yeni proje oluştur", + "open_projects_menu": "Projeler menüsünü aç", + "close_projects_menu": "Projeler menüsünü kapat", + "toggle_quick_actions_menu": "Hızlı eylemler menüsünü aç/kapat", + "open_project_menu": "Proje menüsünü aç", + "close_project_menu": "Proje menüsünü kapat", + "collapse_sidebar": "Kenar çubuğunu daralt", + "expand_sidebar": "Kenar çubuğunu genişlet", + "edition_badge": "Ücretli planlar modalını aç" + } + } +} \ No newline at end of file diff --git a/packages/i18n/src/locales/ua/accessibility.json b/packages/i18n/src/locales/ua/accessibility.json new file mode 100644 index 00000000000..b6bdc7d52be --- /dev/null +++ b/packages/i18n/src/locales/ua/accessibility.json @@ -0,0 +1,27 @@ +{ + "aria_labels": { + "projects_sidebar": { + "workspace_logo": "Логотип робочого простору", + "open_workspace_switcher": "Відкрити перемикач робочого простору", + "open_user_menu": "Відкрити меню користувача", + "open_command_palette": "Відкрити палітру команд", + "open_extended_sidebar": "Відкрити розширену бічну панель", + "close_extended_sidebar": "Закрити розширену бічну панель", + "create_favorites_folder": "Створити папку улюблених", + "open_folder": "Відкрити папку", + "close_folder": "Закрити папку", + "open_favorites_menu": "Відкрити меню улюблених", + "close_favorites_menu": "Закрити меню улюблених", + "enter_folder_name": "Введіть назву папки", + "create_new_project": "Створити новий проект", + "open_projects_menu": "Відкрити меню проектів", + "close_projects_menu": "Закрити меню проектів", + "toggle_quick_actions_menu": "Перемкнути меню швидких дій", + "open_project_menu": "Відкрити меню проекту", + "close_project_menu": "Закрити меню проекту", + "collapse_sidebar": "Згорнути бічну панель", + "expand_sidebar": "Розгорнути бічну панель", + "edition_badge": "Відкрити модал платних планів" + } + } +} \ No newline at end of file diff --git a/packages/i18n/src/locales/vi-VN/accessibility.json b/packages/i18n/src/locales/vi-VN/accessibility.json new file mode 100644 index 00000000000..8071da9e388 --- /dev/null +++ b/packages/i18n/src/locales/vi-VN/accessibility.json @@ -0,0 +1,27 @@ +{ + "aria_labels": { + "projects_sidebar": { + "workspace_logo": "Logo không gian làm việc", + "open_workspace_switcher": "Mở trình chuyển đổi không gian làm việc", + "open_user_menu": "Mở menu người dùng", + "open_command_palette": "Mở bảng lệnh", + "open_extended_sidebar": "Mở thanh bên mở rộng", + "close_extended_sidebar": "Đóng thanh bên mở rộng", + "create_favorites_folder": "Tạo thư mục yêu thích", + "open_folder": "Mở thư mục", + "close_folder": "Đóng thư mục", + "open_favorites_menu": "Mở menu yêu thích", + "close_favorites_menu": "Đóng menu yêu thích", + "enter_folder_name": "Nhập tên thư mục", + "create_new_project": "Tạo dự án mới", + "open_projects_menu": "Mở menu dự án", + "close_projects_menu": "Đóng menu dự án", + "toggle_quick_actions_menu": "Bật/tắt menu hành động nhanh", + "open_project_menu": "Mở menu dự án", + "close_project_menu": "Đóng menu dự án", + "collapse_sidebar": "Thu gọn thanh bên", + "expand_sidebar": "Mở rộng thanh bên", + "edition_badge": "Mở modal gói trả phí" + } + } +} \ No newline at end of file diff --git a/packages/i18n/src/locales/zh-CN/accessibility.json b/packages/i18n/src/locales/zh-CN/accessibility.json new file mode 100644 index 00000000000..b19f68676ac --- /dev/null +++ b/packages/i18n/src/locales/zh-CN/accessibility.json @@ -0,0 +1,27 @@ +{ + "aria_labels": { + "projects_sidebar": { + "workspace_logo": "工作空间徽标", + "open_workspace_switcher": "打开工作空间切换器", + "open_user_menu": "打开用户菜单", + "open_command_palette": "打开命令面板", + "open_extended_sidebar": "打开扩展侧边栏", + "close_extended_sidebar": "关闭扩展侧边栏", + "create_favorites_folder": "创建收藏夹文件夹", + "open_folder": "打开文件夹", + "close_folder": "关闭文件夹", + "open_favorites_menu": "打开收藏夹菜单", + "close_favorites_menu": "关闭收藏夹菜单", + "enter_folder_name": "输入文件夹名称", + "create_new_project": "创建新项目", + "open_projects_menu": "打开项目菜单", + "close_projects_menu": "关闭项目菜单", + "toggle_quick_actions_menu": "切换快速操作菜单", + "open_project_menu": "打开项目菜单", + "close_project_menu": "关闭项目菜单", + "collapse_sidebar": "折叠侧边栏", + "expand_sidebar": "展开侧边栏", + "edition_badge": "打开付费计划模态框" + } + } +} \ No newline at end of file diff --git a/packages/i18n/src/locales/zh-TW/accessibility.json b/packages/i18n/src/locales/zh-TW/accessibility.json new file mode 100644 index 00000000000..97e07ae73b9 --- /dev/null +++ b/packages/i18n/src/locales/zh-TW/accessibility.json @@ -0,0 +1,27 @@ +{ + "aria_labels": { + "projects_sidebar": { + "workspace_logo": "工作空間標誌", + "open_workspace_switcher": "打開工作空間切換器", + "open_user_menu": "打開用戶選單", + "open_command_palette": "打開命令面板", + "open_extended_sidebar": "打開擴展側邊欄", + "close_extended_sidebar": "關閉擴展側邊欄", + "create_favorites_folder": "創建收藏夾文件夾", + "open_folder": "打開文件夾", + "close_folder": "關閉文件夾", + "open_favorites_menu": "打開收藏夾選單", + "close_favorites_menu": "關閉收藏夾選單", + "enter_folder_name": "輸入文件夾名稱", + "create_new_project": "創建新項目", + "open_projects_menu": "打開項目選單", + "close_projects_menu": "關閉項目選單", + "toggle_quick_actions_menu": "切換快速操作選單", + "open_project_menu": "打開項目選單", + "close_project_menu": "關閉項目選單", + "collapse_sidebar": "摺疊側邊欄", + "expand_sidebar": "展開側邊欄", + "edition_badge": "打開付費計劃模態框" + } + } +} \ No newline at end of file diff --git a/packages/i18n/src/store/index.ts b/packages/i18n/src/store/index.ts index ff4cee10762..c75d7b8a324 100644 --- a/packages/i18n/src/store/index.ts +++ b/packages/i18n/src/store/index.ts @@ -3,7 +3,7 @@ import get from "lodash/get"; import merge from "lodash/merge"; import { makeAutoObservable, runInAction } from "mobx"; // constants -import { FALLBACK_LANGUAGE, SUPPORTED_LANGUAGES, LANGUAGE_STORAGE_KEY } from "../constants"; +import { FALLBACK_LANGUAGE, SUPPORTED_LANGUAGES, LANGUAGE_STORAGE_KEY, ETranslationFiles } from "../constants"; // core translations imports import coreEn from "../locales/en/core.json"; // types @@ -130,54 +130,32 @@ export class TranslationStore { } } + /** + * Helper function to import and merge multiple translation files for a language + * @param language - The language code + * @param files - Array of file names to import (without .json extension) + * @returns Promise that resolves to merged translations + */ + private async importAndMergeFiles(language: TLanguage, files: string[]): Promise { + try { + const importPromises = files.map((file) => import(`../locales/${language}/${file}.json`)); + + const modules = await Promise.all(importPromises); + const merged = modules.reduce((acc, module) => merge(acc, module.default), {}); + return { default: merged }; + } catch (error) { + throw new Error(`Failed to import and merge files for ${language}: ${error}`); + } + } + /** * Imports the translations for the given language * @param language - The language to import the translations for * @returns {Promise} */ - private importLanguageFile(language: TLanguage): Promise { - switch (language) { - case "en": - return import("../locales/en/translations.json"); - case "fr": - return import("../locales/fr/translations.json"); - case "es": - return import("../locales/es/translations.json"); - case "ja": - return import("../locales/ja/translations.json"); - case "zh-CN": - return import("../locales/zh-CN/translations.json"); - case "zh-TW": - return import("../locales/zh-TW/translations.json"); - case "ru": - return import("../locales/ru/translations.json"); - case "it": - return import("../locales/it/translations.json"); - case "cs": - return import("../locales/cs/translations.json"); - case "sk": - return import("../locales/sk/translations.json"); - case "de": - return import("../locales/de/translations.json"); - case "ua": - return import("../locales/ua/translations.json"); - case "pl": - return import("../locales/pl/translations.json"); - case "ko": - return import("../locales/ko/translations.json"); - case "pt-BR": - return import("../locales/pt-BR/translations.json"); - case "id": - return import("../locales/id/translations.json"); - case "ro": - return import("../locales/ro/translations.json"); - case "vi-VN": - return import("../locales/vi-VN/translations.json"); - case "tr-TR": - return import("../locales/tr-TR/translations.json"); - default: - throw new Error(`Unsupported language: ${language}`); - } + private async importLanguageFile(language: TLanguage): Promise { + const files = Object.values(ETranslationFiles); + return this.importAndMergeFiles(language, files); } /** Checks if the language is valid based on the supported languages */ diff --git a/packages/ui/src/avatar/avatar.tsx b/packages/ui/src/avatar/avatar.tsx index 0c57ccebabb..84a8ab89558 100644 --- a/packages/ui/src/avatar/avatar.tsx +++ b/packages/ui/src/avatar/avatar.tsx @@ -160,7 +160,7 @@ export const Avatar: React.FC = (props) => { color: fallbackTextColor ?? "#ffffff", }} > - {name ? name[0].toUpperCase() : fallbackText ?? "?"} + {name?.[0]?.toUpperCase() ?? fallbackText ?? "?"} )} diff --git a/packages/ui/src/dropdowns/custom-menu.tsx b/packages/ui/src/dropdowns/custom-menu.tsx index 24c8a106a08..688f1489749 100644 --- a/packages/ui/src/dropdowns/custom-menu.tsx +++ b/packages/ui/src/dropdowns/custom-menu.tsx @@ -14,6 +14,7 @@ import { ICustomMenuDropdownProps, ICustomMenuItemProps } from "./helper"; const CustomMenu = (props: ICustomMenuDropdownProps) => { const { + ariaLabel, buttonClassName = "", customButtonClassName = "", customButtonTabIndex = 0, @@ -75,7 +76,7 @@ const CustomMenu = (props: ICustomMenuDropdownProps) => { e.stopPropagation(); e.preventDefault(); isOpen ? closeDropdown() : openDropdown(); - if (menuButtonOnClick) menuButtonOnClick(); + menuButtonOnClick?.(); }; const handleMouseEnter = () => { @@ -147,6 +148,7 @@ const CustomMenu = (props: ICustomMenuDropdownProps) => { className={customButtonClassName} tabIndex={customButtonTabIndex} disabled={disabled} + aria-label={ariaLabel} > {customButton} @@ -164,6 +166,7 @@ const CustomMenu = (props: ICustomMenuDropdownProps) => { disabled ? "cursor-not-allowed" : "cursor-pointer hover:bg-custom-background-80" } ${buttonClassName}`} tabIndex={customButtonTabIndex} + aria-label={ariaLabel} > @@ -183,6 +186,7 @@ const CustomMenu = (props: ICustomMenuDropdownProps) => { onClick={handleMenuButtonClick} tabIndex={customButtonTabIndex} disabled={disabled} + aria-label={ariaLabel} > {label} {!noChevron && } diff --git a/packages/ui/src/dropdowns/helper.tsx b/packages/ui/src/dropdowns/helper.tsx index 0e758705110..1d40acef795 100644 --- a/packages/ui/src/dropdowns/helper.tsx +++ b/packages/ui/src/dropdowns/helper.tsx @@ -32,6 +32,7 @@ export interface ICustomMenuDropdownProps extends IDropdownProps { closeOnSelect?: boolean; portalElement?: Element | null; openOnHover?: boolean; + ariaLabel?: string; } export interface ICustomSelectProps extends IDropdownProps { diff --git a/web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar.tsx b/web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar.tsx index e0003eeba5a..baa41eb9fb9 100644 --- a/web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar.tsx +++ b/web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar.tsx @@ -96,7 +96,7 @@ export const ExtendedAppSidebar = observer(() => { useExtendedSidebarOutsideClickDetector( extendedSidebarRef, - () => toggleExtendedSidebar(false), + () => toggleExtendedSidebar(true), "extended-sidebar-toggle" ); @@ -106,8 +106,8 @@ export const ExtendedAppSidebar = observer(() => { className={cn( "absolute top-0 h-full z-[19] flex flex-col gap-0.5 w-[300px] transform transition-all duration-300 ease-in-out bg-custom-sidebar-background-100 border-r border-custom-sidebar-border-200 p-4 shadow-md pb-6", { - "translate-x-0 opacity-100 pointer-events-auto": extendedSidebarCollapsed, - "-translate-x-full opacity-0 pointer-events-none": !extendedSidebarCollapsed, + "-translate-x-full opacity-0 pointer-events-none": extendedSidebarCollapsed, + "translate-x-0 opacity-100 pointer-events-auto": !extendedSidebarCollapsed, "left-[70px]": sidebarCollapsed, "left-[250px]": !sidebarCollapsed, } diff --git a/web/ce/components/workspace/edition-badge.tsx b/web/ce/components/workspace/edition-badge.tsx index b32ce9e61ad..e0fefc3568c 100644 --- a/web/ce/components/workspace/edition-badge.tsx +++ b/web/ce/components/workspace/edition-badge.tsx @@ -1,7 +1,8 @@ import { useState } from "react"; import { observer } from "mobx-react"; import packageJson from "package.json"; -// ui +// plane imports +import { useTranslation } from "@plane/i18n"; import { Button, Tooltip } from "@plane/ui"; // hooks import { usePlatformOS } from "@/hooks/use-platform-os"; @@ -9,9 +10,12 @@ import { usePlatformOS } from "@/hooks/use-platform-os"; import { PaidPlanUpgradeModal } from "../license"; export const WorkspaceEditionBadge = observer(() => { - const { isMobile } = usePlatformOS(); // states const [isPaidPlanPurchaseModalOpen, setIsPaidPlanPurchaseModalOpen] = useState(false); + // translation + const { t } = useTranslation(); + // platform + const { isMobile } = usePlatformOS(); return ( <> @@ -25,6 +29,8 @@ export const WorkspaceEditionBadge = observer(() => { variant="accent-primary" className="w-fit min-w-24 cursor-pointer rounded-2xl px-2 py-1 text-center text-sm font-medium outline-none" onClick={() => setIsPaidPlanPurchaseModalOpen(true)} + aria-haspopup="dialog" + aria-label={t("aria_labels.projects_sidebar.edition_badge")} > Community diff --git a/web/ce/components/workspace/sidebar/app-search.tsx b/web/ce/components/workspace/sidebar/app-search.tsx index 6ab92b99604..1ba0ea72c2a 100644 --- a/web/ce/components/workspace/sidebar/app-search.tsx +++ b/web/ce/components/workspace/sidebar/app-search.tsx @@ -1,5 +1,7 @@ import { observer } from "mobx-react"; import { Search } from "lucide-react"; +// plane imports +import { useTranslation } from "@plane/i18n"; // helpers import { cn } from "@/helpers/common.helper"; // hooks @@ -9,9 +11,12 @@ export const AppSearch = observer(() => { // store hooks const { sidebarCollapsed } = useAppTheme(); const { toggleCommandPaletteModal } = useCommandPalette(); + // translation + const { t } = useTranslation(); return ( diff --git a/web/ce/components/workspace/sidebar/extended-sidebar-item.tsx b/web/ce/components/workspace/sidebar/extended-sidebar-item.tsx index 5bb2fe885f5..5e7343e0a8a 100644 --- a/web/ce/components/workspace/sidebar/extended-sidebar-item.tsx +++ b/web/ce/components/workspace/sidebar/extended-sidebar-item.tsx @@ -55,7 +55,7 @@ export const ExtendedSidebarItem: FC = observer((prop const sidebarPreference = getNavigationPreferences(workspaceSlug.toString()); const isPinned = sidebarPreference?.[item.key]?.is_pinned; - const handleLinkClick = () => toggleExtendedSidebar(); + const handleLinkClick = () => toggleExtendedSidebar(true); if (!allowPermissions(item.access as any, EUserPermissionsLevel.WORKSPACE, workspaceSlug.toString())) { return null; diff --git a/web/ce/components/workspace/sidebar/sidebar-item.tsx b/web/ce/components/workspace/sidebar/sidebar-item.tsx index 51a5735de35..3645bde3ddd 100644 --- a/web/ce/components/workspace/sidebar/sidebar-item.tsx +++ b/web/ce/components/workspace/sidebar/sidebar-item.tsx @@ -38,7 +38,7 @@ export const SidebarItem: FC = observer((props) => { if (window.innerWidth < 768) { toggleSidebar(); } - if (extendedSidebarCollapsed) toggleExtendedSidebar(); + if (!extendedSidebarCollapsed) toggleExtendedSidebar(); }; const staticItems = ["home", "inbox", "pi-chat", "projects"]; diff --git a/web/ce/constants/sidebar-favorites.ts b/web/ce/constants/sidebar-favorites.ts index 9fa80e05f47..a6f49f8aaf8 100644 --- a/web/ce/constants/sidebar-favorites.ts +++ b/web/ce/constants/sidebar-favorites.ts @@ -1,7 +1,7 @@ -import { Briefcase, ContrastIcon, FileText, Layers, LucideIcon } from "lucide-react"; +import { Briefcase, FileText, Layers, LucideIcon } from "lucide-react"; // plane imports import { IFavorite } from "@plane/types"; -import { DiceIcon, FavoriteFolderIcon, ISvgIcons } from "@plane/ui"; +import { ContrastIcon, DiceIcon, FavoriteFolderIcon, ISvgIcons } from "@plane/ui"; export const FAVORITE_ITEM_ICONS: Record | LucideIcon> = { page: FileText, diff --git a/web/core/components/workspace/logo.tsx b/web/core/components/workspace/logo.tsx index 460e076c5fc..f25615dfc22 100644 --- a/web/core/components/workspace/logo.tsx +++ b/web/core/components/workspace/logo.tsx @@ -1,4 +1,6 @@ -// plane utils +import { observer } from "mobx-react"; +// plane imports +import { useTranslation } from "@plane/i18n"; import { cn } from "@plane/utils"; // helpers import { getFileURL } from "@/helpers/file.helper"; @@ -9,22 +11,27 @@ type Props = { classNames?: string; }; -export const WorkspaceLogo = (props: Props) => ( -
- {props.logo && props.logo !== "" ? ( - Workspace Logo - ) : ( - (props.name?.charAt(0) ?? "...") - )} -
-); +export const WorkspaceLogo = observer((props: Props) => { + // translation + const { t } = useTranslation(); + + return ( +
+ {props.logo && props.logo !== "" ? ( + {t("aria_labels.projects_sidebar.workspace_logo")} + ) : ( + (props.name?.[0] ?? "...") + )} +
+ ); +}); diff --git a/web/core/components/workspace/sidebar/dropdown.tsx b/web/core/components/workspace/sidebar/dropdown.tsx index f9e2aca5989..b4e6b93d7b0 100644 --- a/web/core/components/workspace/sidebar/dropdown.tsx +++ b/web/core/components/workspace/sidebar/dropdown.tsx @@ -25,21 +25,17 @@ import { WorkspaceLogo } from "../logo"; import SidebarDropdownItem from "./dropdown-item"; export const SidebarDropdown = observer(() => { - const { t } = useTranslation(); - // store hooks const { sidebarCollapsed, toggleSidebar } = useAppTheme(); const { data: currentUser } = useUser(); - const { - // updateCurrentUser, - // isUserInstanceAdmin, - signOut, - } = useUser(); + const { signOut } = useUser(); const { updateUserProfile } = useUserProfile(); + const { currentWorkspace: activeWorkspace, workspaces } = useWorkspace(); + // derived values const isWorkspaceCreationEnabled = getIsWorkspaceCreationDisabled() === false; - const isUserInstanceAdmin = false; - const { currentWorkspace: activeWorkspace, workspaces } = useWorkspace(); + // translation + const { t } = useTranslation(); // popper-js refs const [referenceElement, setReferenceElement] = useState(null); const [popperElement, setPopperElement] = useState(null); @@ -87,6 +83,7 @@ export const SidebarDropdown = observer(() => { "group/menu-button flex items-center justify-between gap-1 p-1 truncate rounded text-sm font-medium text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-80 focus:outline-none", { "flex-grow": !sidebarCollapsed } )} + aria-label={t("aria_labels.projects_sidebar.open_workspace_switcher")} >
@@ -190,7 +187,11 @@ export const SidebarDropdown = observer(() => { )} - + = (props) => { const [isDragging, setIsDragging] = useState(false); const [folderToRename, setFolderToRename] = useState(null); const [instruction, setInstruction] = useState(undefined); - // refs const actionSectionRef = useRef(null); const elementRef = useRef(null); + // translation + const { t } = useTranslation(); useEffect(() => { if (favorite.children === undefined && workspaceSlug) { @@ -231,11 +231,11 @@ export const FavoriteFolder: React.FC = (props) => { setIsMenuActive(!isMenuActive)} > - + } + menuButtonOnClick={() => setIsMenuActive(!isMenuActive)} className={cn( "opacity-0 pointer-events-none flex-shrink-0 group-hover/project-item:opacity-100 group-hover/project-item:pointer-events-auto", { @@ -244,6 +244,7 @@ export const FavoriteFolder: React.FC = (props) => { )} customButtonClassName="grid place-items-center" placement="bottom-start" + ariaLabel={t("aria_labels.projects_sidebar.toggle_quick_actions_menu")} > handleRemoveFromFavorites(favorite)}> @@ -267,9 +268,12 @@ export const FavoriteFolder: React.FC = (props) => { "inline-block": isMenuActive, } )} + aria-label={t( + open ? "aria_labels.projects_sidebar.close_folder" : "aria_labels.projects_sidebar.open_folder" + )} > diff --git a/web/core/components/workspace/sidebar/favorites/favorite-items/common/favorite-item-quick-action.tsx b/web/core/components/workspace/sidebar/favorites/favorite-items/common/favorite-item-quick-action.tsx index eadaedb3458..cf6436733f4 100644 --- a/web/core/components/workspace/sidebar/favorites/favorite-items/common/favorite-item-quick-action.tsx +++ b/web/core/components/workspace/sidebar/favorites/favorite-items/common/favorite-item-quick-action.tsx @@ -1,8 +1,10 @@ "use client"; import React, { FC } from "react"; +import { observer } from "mobx-react"; import { MoreHorizontal, Star } from "lucide-react"; +// plane imports +import { useTranslation } from "@plane/i18n"; import { IFavorite } from "@plane/types"; -// ui import { CustomMenu } from "@plane/ui"; // helpers import { cn } from "@/helpers/common.helper"; @@ -15,19 +17,22 @@ type Props = { handleRemoveFromFavorites: (favorite: IFavorite) => void; }; -export const FavoriteItemQuickAction: FC = (props) => { +export const FavoriteItemQuickAction: FC = observer((props) => { const { ref, isMenuActive, onChange, handleRemoveFromFavorites, favorite } = props; + // translation + const { t } = useTranslation(); + return ( onChange(!isMenuActive)} > } + menuButtonOnClick={() => onChange(!isMenuActive)} className={cn( "opacity-0 pointer-events-none flex-shrink-0 group-hover/project-item:opacity-100 group-hover/project-item:pointer-events-auto", { @@ -36,6 +41,7 @@ export const FavoriteItemQuickAction: FC = (props) => { )} customButtonClassName="grid place-items-center" placement="bottom-start" + ariaLabel={t("aria_labels.projects_sidebar.toggle_quick_actions_menu")} > handleRemoveFromFavorites(favorite)}> @@ -45,4 +51,4 @@ export const FavoriteItemQuickAction: FC = (props) => { ); -}; +}); diff --git a/web/core/components/workspace/sidebar/favorites/favorites-menu.tsx b/web/core/components/workspace/sidebar/favorites/favorites-menu.tsx index 2beed74f66b..f83f0ed061b 100644 --- a/web/core/components/workspace/sidebar/favorites/favorites-menu.tsx +++ b/web/core/components/workspace/sidebar/favorites/favorites-menu.tsx @@ -34,13 +34,12 @@ import { getInstructionFromPayload, TargetData } from "./favorites.helpers"; import { NewFavoriteFolder } from "./new-fav-folder"; export const SidebarFavoritesMenu = observer(() => { - //state + // states const [createNewFolder, setCreateNewFolder] = useState(null); - const [isDragging, setIsDragging] = useState(false); - + // navigation + const { workspaceSlug } = useParams(); // store hooks - const { t } = useTranslation(); const { sidebarCollapsed } = useAppTheme(); const { favoriteIds, @@ -50,17 +49,17 @@ export const SidebarFavoritesMenu = observer(() => { reOrderFavorite, moveFavoriteToFolder, } = useFavorite(); - const { workspaceSlug } = useParams(); - + // translation + const { t } = useTranslation(); + // platform hooks const { isMobile } = usePlatformOS(); - // local storage const { setValue: toggleFavoriteMenu, storedValue } = useLocalStorage(IS_FAVORITE_MENU_OPEN, false); // derived values const isFavoriteMenuOpen = !!storedValue; // refs - const containerRef = useRef(null); - const elementRef = useRef(null); + const containerRef = useRef(null); + const elementRef = useRef(null); const handleMoveToFolder = (sourceId: string, destinationId: string) => { moveFavoriteToFolder(workspaceSlug.toString(), sourceId, { @@ -131,6 +130,7 @@ export const SidebarFavoritesMenu = observer(() => { }); }); }; + const handleRemoveFromFavoritesFolder = (favoriteId: string) => { removeFromFavoriteFolder(workspaceSlug.toString(), favoriteId).catch(() => { setToast({ @@ -151,7 +151,7 @@ export const SidebarFavoritesMenu = observer(() => { }); }); }, - [workspaceSlug, reOrderFavorite] + [workspaceSlug, reOrderFavorite, t] ); useEffect(() => { @@ -190,37 +190,68 @@ export const SidebarFavoritesMenu = observer(() => { <> {!sidebarCollapsed && ( - - toggleFavoriteMenu(!isFavoriteMenuOpen)} className="flex-1 text-start"> - {t("favorites")} - - + toggleFavoriteMenu(!isFavoriteMenuOpen)} + aria-label={t( + isFavoriteMenuOpen + ? "aria_labels.projects_sidebar.close_favorites_menu" + : "aria_labels.projects_sidebar.open_favorites_menu" + )} + > + {t("favorites")} + +
- { setCreateNewFolder(true); if (!isFavoriteMenuOpen) toggleFavoriteMenu(!isFavoriteMenuOpen); }} - className={cn("size-4 flex-shrink-0 text-custom-sidebar-text-400 transition-transform")} - /> + aria-label={t("aria_labels.projects_sidebar.create_favorites_folder")} + > + + - toggleFavoriteMenu(!isFavoriteMenuOpen)} - className={cn("size-4 flex-shrink-0 text-custom-sidebar-text-400 transition-transform", { - "rotate-90": isFavoriteMenuOpen, - })} - /> - - + aria-label={t( + isFavoriteMenuOpen + ? "aria_labels.projects_sidebar.close_favorites_menu" + : "aria_labels.projects_sidebar.open_favorites_menu" + )} + > + + +
+
)} { name="name" control={control} rules={{ required: true }} - render={({ field }) => } + render={({ field }) => ( + + )} /> diff --git a/web/core/components/workspace/sidebar/help-section.tsx b/web/core/components/workspace/sidebar/help-section.tsx index 04ef02fea86..9c1b98fe8be 100644 --- a/web/core/components/workspace/sidebar/help-section.tsx +++ b/web/core/components/workspace/sidebar/help-section.tsx @@ -175,8 +175,13 @@ export const SidebarHelpSection: React.FC = observer( isCollapsed ? "w-full" : "" }`} onClick={() => toggleSidebar()} + aria-label={t( + isCollapsed + ? "aria_labels.projects_sidebar.expand_sidebar" + : "aria_labels.projects_sidebar.collapse_sidebar" + )} > - + diff --git a/web/core/components/workspace/sidebar/projects-list-item.tsx b/web/core/components/workspace/sidebar/projects-list-item.tsx index 75b10aa4c79..1a813d29598 100644 --- a/web/core/components/workspace/sidebar/projects-list-item.tsx +++ b/web/core/components/workspace/sidebar/projects-list-item.tsx @@ -184,13 +184,13 @@ export const SidebarProjectsListItem: React.FC = observer((props) => { const sourceId = source?.data?.id as string | undefined; const destinationId = self?.data?.id as string | undefined; - handleOnProjectDrop && handleOnProjectDrop(sourceId, destinationId, currentInstruction === "DRAG_BELOW"); + handleOnProjectDrop?.(sourceId, destinationId, currentInstruction === "DRAG_BELOW"); highlightIssueOnDrop(`sidebar-${sourceId}-${projectListType}`); }, }) ); - }, [projectRef?.current, dragHandleRef?.current, projectId, isLastChild, projectListType, handleOnProjectDrop]); + }, [projectId, isLastChild, projectListType, handleOnProjectDrop]); useOutsideClickDetector(actionSectionRef, () => setIsMenuActive(false)); useOutsideClickDetector(projectRef, () => projectRef?.current?.classList?.remove(HIGHLIGHT_CLASS)); @@ -284,6 +284,11 @@ export const SidebarProjectsListItem: React.FC = observer((props) => { className={cn("flex-grow flex items-center gap-1.5 text-left select-none w-full", { "justify-center": isSidebarCollapsed, })} + aria-label={ + isProjectListOpen + ? t("aria_labels.projects_sidebar.close_project_menu") + : t("aria_labels.projects_sidebar.open_project_menu") + } >
@@ -310,6 +315,7 @@ export const SidebarProjectsListItem: React.FC = observer((props) => { )} customButtonClassName="grid place-items-center" placement="bottom-start" + ariaLabel={t("aria_labels.projects_sidebar.toggle_quick_actions_menu")} useCaptureForOutsideClick > {/* TODO: Removed is_favorite logic due to the optimization in projects API */} @@ -383,6 +389,11 @@ export const SidebarProjectsListItem: React.FC = observer((props) => { } )} onClick={() => setIsProjectListOpen(!isProjectListOpen)} + aria-label={t( + isProjectListOpen + ? "aria_labels.projects_sidebar.close_project_menu" + : "aria_labels.projects_sidebar.open_project_menu" + )} > { as="button" type="button" className={cn( - "group w-full flex items-center gap-1 whitespace-nowrap text-left text-sm font-semibold text-custom-sidebar-text-400", + "w-full flex items-center gap-1 whitespace-nowrap text-left text-sm font-semibold text-custom-sidebar-text-400", { "!text-center w-8 px-2 py-1.5 justify-center": isCollapsed, } )} onClick={() => toggleListDisclosure(!isAllProjectsListOpen)} + aria-label={t( + isAllProjectsListOpen + ? "aria_labels.projects_sidebar.close_projects_menu" + : "aria_labels.projects_sidebar.open_projects_menu" + )} > <> @@ -195,6 +200,7 @@ export const SidebarProjectsList: FC = observer(() => { setTrackElement(`APP_SIDEBAR_JOINED_BLOCK`); setIsProjectModalOpen(true); }} + aria-label={t("aria_labels.projects_sidebar.create_new_project")} > @@ -205,9 +211,14 @@ export const SidebarProjectsList: FC = observer(() => { type="button" className="p-0.5 rounded hover:bg-custom-sidebar-background-80 flex-shrink-0" onClick={() => toggleListDisclosure(!isAllProjectsListOpen)} + aria-label={t( + isAllProjectsListOpen + ? "aria_labels.projects_sidebar.close_projects_menu" + : "aria_labels.projects_sidebar.open_projects_menu" + )} > diff --git a/web/core/components/workspace/sidebar/quick-actions.tsx b/web/core/components/workspace/sidebar/quick-actions.tsx index 150c08d6838..86ab8960300 100644 --- a/web/core/components/workspace/sidebar/quick-actions.tsx +++ b/web/core/components/workspace/sidebar/quick-actions.tsx @@ -46,7 +46,9 @@ export const SidebarQuickActions = observer(() => { const handleMouseEnter = () => { // if enter before time out clear the timeout - timeoutRef?.current && clearTimeout(timeoutRef.current); + if (timeoutRef?.current) { + clearTimeout(timeoutRef.current); + } setIsDraftButtonOpen(true); }; diff --git a/web/core/components/workspace/sidebar/sidebar-menu-items.tsx b/web/core/components/workspace/sidebar/sidebar-menu-items.tsx index bedfa02a30d..89c0f150eaa 100644 --- a/web/core/components/workspace/sidebar/sidebar-menu-items.tsx +++ b/web/core/components/workspace/sidebar/sidebar-menu-items.tsx @@ -8,6 +8,7 @@ import { WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS_LINKS, WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS_LINKS, } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; import { cn } from "@plane/utils"; // components import { SidebarNavItem } from "@/components/sidebar"; @@ -20,9 +21,10 @@ export const SidebarMenuItems = observer(() => { // routers const { workspaceSlug } = useParams(); // store hooks - const { sidebarCollapsed, toggleExtendedSidebar } = useAppTheme(); + const { sidebarCollapsed, extendedSidebarCollapsed, toggleExtendedSidebar } = useAppTheme(); const { getNavigationPreferences } = useWorkspace(); - + // translation + const { t } = useTranslation(); // derived values const currentWorkspaceNavigationPreferences = getNavigationPreferences(workspaceSlug.toString()); @@ -39,31 +41,35 @@ export const SidebarMenuItems = observer(() => { ); return ( - <> -
- {WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS_LINKS.map((item, _index) => ( - - ))} - {sortedNavigationItems.map((item, _index) => ( - - ))} - - - -
- +
+ {WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS_LINKS.map((item, _index) => ( + + ))} + {sortedNavigationItems.map((item, _index) => ( + + ))} + + + +
); }); diff --git a/web/core/store/theme.store.ts b/web/core/store/theme.store.ts index a5d961e2db2..b37fb0ef5f3 100644 --- a/web/core/store/theme.store.ts +++ b/web/core/store/theme.store.ts @@ -1,4 +1,4 @@ -import { action, observable, makeObservable } from "mobx"; +import { action, observable, makeObservable, runInAction } from "mobx"; export interface IThemeStore { // observables @@ -26,7 +26,7 @@ export interface IThemeStore { export class ThemeStore implements IThemeStore { // observables sidebarCollapsed: boolean | undefined = undefined; - extendedSidebarCollapsed: boolean | undefined = undefined; + extendedSidebarCollapsed: boolean | undefined = true; extendedProjectSidebarCollapsed: boolean | undefined = undefined; profileSidebarCollapsed: boolean | undefined = undefined; workspaceAnalyticsSidebarCollapsed: boolean | undefined = undefined; @@ -78,12 +78,11 @@ export class ThemeStore implements IThemeStore { * @param collapsed */ toggleExtendedSidebar = (collapsed?: boolean) => { - if (collapsed === undefined) { - this.extendedSidebarCollapsed = !this.extendedSidebarCollapsed; - } else { - this.extendedSidebarCollapsed = collapsed; - } - localStorage.setItem("extended_sidebar_collapsed", this.extendedSidebarCollapsed.toString()); + const updatedState = collapsed ?? !this.extendedSidebarCollapsed; + runInAction(() => { + this.extendedSidebarCollapsed = updatedState; + }); + localStorage.setItem("extended_sidebar_collapsed", updatedState.toString()); }; /**