fix(web): show plugin auth permission hint (#37310)

This commit is contained in:
Jingyi 2026-06-10 20:24:39 -07:00 committed by GitHub
parent 117a25b32a
commit 49c97a3f61
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 200 additions and 19 deletions

View File

@ -1,22 +1,16 @@
import { cleanup, render, screen } from '@testing-library/react'
import { cleanup, fireEvent, render, screen } from '@testing-library/react'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { ACCOUNT_SETTING_TAB } from '@/app/components/header/account-setting/constants'
import PluginAuth from '../plugin-auth'
import { AuthCategory } from '../types'
const mockUsePluginAuth = vi.fn()
const mockSetShowAccountSettingModal = vi.fn()
vi.mock('../hooks/use-plugin-auth', () => ({
usePluginAuth: (...args: unknown[]) => mockUsePluginAuth(...args),
}))
vi.mock('../authorize', () => ({
default: ({ pluginPayload }: { pluginPayload: { provider: string } }) => (
<div data-testid="authorize">
Authorize:
{pluginPayload.provider}
</div>
),
}))
vi.mock('../authorized', () => ({
default: ({ pluginPayload }: { pluginPayload: { provider: string } }) => (
<div data-testid="authorized">
@ -26,6 +20,12 @@ vi.mock('../authorized', () => ({
),
}))
vi.mock('@/context/modal-context', () => ({
useModalContext: () => ({
setShowAccountSettingModal: mockSetShowAccountSettingModal,
}),
}))
const defaultPayload = {
category: AuthCategory.tool,
provider: 'test-provider',
@ -52,7 +52,7 @@ describe('PluginAuth', () => {
})
render(<PluginAuth pluginPayload={defaultPayload} />)
expect(screen.getByTestId('authorize')).toBeInTheDocument()
expect(screen.getByRole('button', { name: 'plugin.auth.useApiAuth' })).toBeEnabled()
expect(screen.queryByTestId('authorized')).not.toBeInTheDocument()
})
@ -136,4 +136,74 @@ describe('PluginAuth', () => {
render(<PluginAuth pluginPayload={defaultPayload} />)
expect(mockUsePluginAuth).toHaveBeenCalledWith(defaultPayload, true)
})
it('renders permission hint when authorization configuration is disabled by workspace permissions', () => {
mockUsePluginAuth.mockReturnValue({
isAuthorized: false,
canOAuth: false,
canApiKey: true,
credentials: [],
disabled: true,
invalidPluginCredentialInfo: vi.fn(),
notAllowCustomCredential: false,
})
render(<PluginAuth pluginPayload={defaultPayload} />)
expect(screen.getByRole('button', { name: 'plugin.auth.useApiAuth' })).toBeDisabled()
expect(screen.getByText('plugin.auth.permissionHint.title')).toBeInTheDocument()
expect(screen.getByText('plugin.auth.permissionHint.description')).toBeInTheDocument()
expect(screen.getByRole('button', { name: 'plugin.auth.permissionHint.action' })).toBeInTheDocument()
})
it('opens members settings when permission hint action is clicked', () => {
mockUsePluginAuth.mockReturnValue({
isAuthorized: false,
canOAuth: false,
canApiKey: true,
credentials: [],
disabled: true,
invalidPluginCredentialInfo: vi.fn(),
notAllowCustomCredential: false,
})
render(<PluginAuth pluginPayload={defaultPayload} />)
fireEvent.click(screen.getByRole('button', { name: 'plugin.auth.permissionHint.action' }))
expect(mockSetShowAccountSettingModal).toHaveBeenCalledWith({
payload: ACCOUNT_SETTING_TAB.MEMBERS,
})
})
it('does not render permission hint for datasource authorization', () => {
mockUsePluginAuth.mockReturnValue({
isAuthorized: false,
canOAuth: false,
canApiKey: true,
credentials: [],
disabled: true,
invalidPluginCredentialInfo: vi.fn(),
notAllowCustomCredential: false,
})
render(<PluginAuth pluginPayload={{ ...defaultPayload, category: AuthCategory.datasource }} />)
expect(screen.queryByText('plugin.auth.permissionHint.title')).not.toBeInTheDocument()
})
it('does not render permission hint when custom credentials are unavailable', () => {
mockUsePluginAuth.mockReturnValue({
isAuthorized: false,
canOAuth: false,
canApiKey: true,
credentials: [],
disabled: true,
invalidPluginCredentialInfo: vi.fn(),
notAllowCustomCredential: true,
})
render(<PluginAuth pluginPayload={defaultPayload} />)
expect(screen.queryByText('plugin.auth.permissionHint.title')).not.toBeInTheDocument()
})
})

View File

@ -1,9 +1,13 @@
import type { PluginPayload } from './types'
import { cn } from '@langgenius/dify-ui/cn'
import { memo } from 'react'
import { useTranslation } from 'react-i18next'
import { ACCOUNT_SETTING_TAB } from '@/app/components/header/account-setting/constants'
import { useModalContext } from '@/context/modal-context'
import Authorize from './authorize'
import Authorized from './authorized'
import { usePluginAuth } from './hooks/use-plugin-auth'
import { AuthCategory } from './types'
type PluginAuthProps = {
pluginPayload: PluginPayload
@ -15,6 +19,8 @@ const PluginAuth = ({
children,
className,
}: PluginAuthProps) => {
const { t } = useTranslation()
const { setShowAccountSettingModal } = useModalContext()
const {
isAuthorized,
canOAuth,
@ -24,19 +30,55 @@ const PluginAuth = ({
invalidPluginCredentialInfo,
notAllowCustomCredential,
} = usePluginAuth(pluginPayload, !!pluginPayload.provider)
const showPermissionHint = !isAuthorized
&& disabled
&& !notAllowCustomCredential
&& pluginPayload.category === AuthCategory.tool
&& (canOAuth || canApiKey)
const authorizeContent = (
<Authorize
pluginPayload={pluginPayload}
canOAuth={canOAuth}
canApiKey={canApiKey}
disabled={disabled}
onUpdate={invalidPluginCredentialInfo}
notAllowCustomCredential={notAllowCustomCredential}
/>
)
return (
<div className={cn(!isAuthorized && className)}>
{
!isAuthorized && (
<Authorize
pluginPayload={pluginPayload}
canOAuth={canOAuth}
canApiKey={canApiKey}
disabled={disabled}
onUpdate={invalidPluginCredentialInfo}
notAllowCustomCredential={notAllowCustomCredential}
/>
<>
{authorizeContent}
{
showPermissionHint && (
<div className="mt-2 rounded-lg border border-divider-subtle bg-background-section-burn px-2.5 py-2">
<div className="flex items-start gap-2">
<span aria-hidden className="mt-0.5 i-ri-lock-2-line size-3.5 shrink-0 text-text-tertiary" />
<div className="min-w-0 grow">
<div className="system-xs-medium text-text-secondary">
{t('auth.permissionHint.title', { ns: 'plugin' })}
</div>
<div className="mt-0.5 system-xs-regular text-text-tertiary">
{t('auth.permissionHint.description', { ns: 'plugin' })}
</div>
<div className="mt-1.5">
<button
type="button"
className="-ml-1.5 rounded-md px-1.5 py-0.5 system-xs-medium text-text-accent hover:bg-state-base-hover focus-visible:ring-1 focus-visible:ring-components-input-border-active focus-visible:outline-hidden"
onClick={() => setShowAccountSettingModal({ payload: ACCOUNT_SETTING_TAB.MEMBERS })}
>
{t('auth.permissionHint.action', { ns: 'plugin' })}
</button>
</div>
</div>
</div>
</div>
)
}
</>
)
}
{

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "إعدادات عميل OAuth",
"auth.onlyAtCreationHint": "لا يمكن تحديده مرة أخرى بعد التبديل",
"auth.onlyAtCreationHintTooltip": "تم تكوينه بواسطة أعضاء آخرين · لا يمكن اختياره مرة أخرى بعد التبديل.",
"auth.permissionHint.action": "من يمكنه المساعدة؟",
"auth.permissionHint.description": "تتم مشاركة تفويض المكوّن الإضافي عبر مساحة العمل. تواصل مع عضو لديه الأذونات المطلوبة للحصول على المساعدة.",
"auth.permissionHint.title": "ليس لديك إذن لتكوين التفويض.",
"auth.personal": "شخصي",
"auth.saveAndAuth": "حفظ وتفويض",
"auth.saveOnly": "حفظ فقط",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "OAuth-Client-Einstellungen",
"auth.onlyAtCreationHint": "Nach dem Umschalten nicht erneut wählbar",
"auth.onlyAtCreationHintTooltip": "Von anderen Mitgliedern konfiguriert · Kann nach dem Wechsel nicht erneut ausgewählt werden.",
"auth.permissionHint.action": "Wer kann helfen?",
"auth.permissionHint.description": "Die Plugin-Autorisierung wird im gesamten Workspace geteilt. Wende dich an ein Mitglied mit den erforderlichen Berechtigungen.",
"auth.permissionHint.title": "Du hast keine Berechtigung, die Autorisierung zu konfigurieren.",
"auth.personal": "Persönlich",
"auth.saveAndAuth": "Speichern und autorisieren",
"auth.saveOnly": "Nur speichern",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "OAuth Client Settings",
"auth.onlyAtCreationHint": "Cannot be selected again after switching",
"auth.onlyAtCreationHintTooltip": "Configured by other members · Cannot be selected again after switching.",
"auth.permissionHint.action": "Who can help?",
"auth.permissionHint.description": "Plugin authorization is shared across the workspace. Contact a member with the required permissions for help.",
"auth.permissionHint.title": "You dont have permission to configure authorization.",
"auth.personal": "Personal",
"auth.saveAndAuth": "Save and Authorize",
"auth.saveOnly": "Save only",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "Configuración del cliente OAuth",
"auth.onlyAtCreationHint": "No se puede volver a seleccionar después de cambiar",
"auth.onlyAtCreationHintTooltip": "Configurado por otros miembros · No se puede volver a seleccionar después de cambiar.",
"auth.permissionHint.action": "¿Quién puede ayudar?",
"auth.permissionHint.description": "La autorización del plugin se comparte en todo el espacio de trabajo. Contacta con un miembro que tenga los permisos necesarios.",
"auth.permissionHint.title": "No tienes permiso para configurar la autorización.",
"auth.personal": "personales",
"auth.saveAndAuth": "Guardar y autorizar",
"auth.saveOnly": "Guardar solo",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "تنظیمات کلاینت اوتور",
"auth.onlyAtCreationHint": "بعد از تعویض نمی توان دوباره انتخاب کرد",
"auth.onlyAtCreationHintTooltip": "پیکربندی شده توسط سایر اعضا · پس از تعویض دوباره انتخاب نمی شود.",
"auth.permissionHint.action": "چه کسی می‌تواند کمک کند؟",
"auth.permissionHint.description": "مجوزدهی افزونه در سراسر فضای کاری مشترک است. برای دریافت کمک با عضوی که مجوزهای لازم را دارد تماس بگیرید.",
"auth.permissionHint.title": "شما اجازه پیکربندی مجوزدهی را ندارید.",
"auth.personal": "شخصی",
"auth.saveAndAuth": "ذخیره و تأیید",
"auth.saveOnly": "فقط ذخیره کنید",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "Paramètres du client OAuth",
"auth.onlyAtCreationHint": "Ne peut pas être sélectionné après le changement",
"auth.onlyAtCreationHintTooltip": "Configuré par d'autres membres · Ne peut pas être sélectionné après le changement.",
"auth.permissionHint.action": "Qui peut aider ?",
"auth.permissionHint.description": "Lautorisation du plugin est partagée dans tout lespace de travail. Contactez un membre disposant des autorisations requises.",
"auth.permissionHint.title": "Vous navez pas lautorisation de configurer lautorisation.",
"auth.personal": "Personnel",
"auth.saveAndAuth": "Enregistrer et autoriser",
"auth.saveOnly": "Sauvegarder seulement",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "OAuth क्लाइंट सेटिंग्स",
"auth.onlyAtCreationHint": "स्विच करने के बाद दोबारा चयन नहीं किया जा सकता",
"auth.onlyAtCreationHintTooltip": "अन्य सदस्यों द्वारा कॉन्फ़िगर किया गया · स्विच करने के बाद दोबारा नहीं चुना जा सकता।",
"auth.permissionHint.action": "कौन मदद कर सकता है?",
"auth.permissionHint.description": "प्लगइन authorization पूरे workspace में साझा होता है। मदद के लिए आवश्यक अनुमतियों वाले सदस्य से संपर्क करें।",
"auth.permissionHint.title": "आपके पास authorization कॉन्फ़िगर करने की अनुमति नहीं है।",
"auth.personal": "निजी",
"auth.saveAndAuth": "सहेजें और अधिकृत करें",
"auth.saveOnly": "बस सहेजें",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "Pengaturan Klien OAuth",
"auth.onlyAtCreationHint": "Tidak dapat dipilih lagi setelah peralihan",
"auth.onlyAtCreationHintTooltip": "Dikonfigurasi oleh anggota lain · Tidak dapat dipilih lagi setelah beralih.",
"auth.permissionHint.action": "Siapa yang bisa membantu?",
"auth.permissionHint.description": "Otorisasi plugin dibagikan di seluruh workspace. Hubungi anggota dengan izin yang diperlukan untuk mendapatkan bantuan.",
"auth.permissionHint.title": "Anda tidak memiliki izin untuk mengonfigurasi otorisasi.",
"auth.personal": "Pribadi",
"auth.saveAndAuth": "Simpan dan Otorisasi",
"auth.saveOnly": "Hanya Hemat",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "Impostazioni del client OAuth",
"auth.onlyAtCreationHint": "Non può essere selezionato nuovamente dopo il passaggio",
"auth.onlyAtCreationHintTooltip": "Configurato da altri membri · Non può essere selezionato nuovamente dopo il passaggio.",
"auth.permissionHint.action": "Chi può aiutare?",
"auth.permissionHint.description": "Lautorizzazione del plugin è condivisa in tutto il workspace. Contatta un membro con le autorizzazioni richieste per ricevere aiuto.",
"auth.permissionHint.title": "Non hai lautorizzazione per configurare lautorizzazione.",
"auth.personal": "Personale",
"auth.saveAndAuth": "Salva e Autorizza",
"auth.saveOnly": "Salva solo",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "OAuthクライアント設定",
"auth.onlyAtCreationHint": "切り替え後は再度選択できません",
"auth.onlyAtCreationHintTooltip": "他のメンバーが設定 ・切り替え後は再度選択できません。",
"auth.permissionHint.action": "誰に相談できますか?",
"auth.permissionHint.description": "プラグインの認可はワークスペース全体で共有されます。必要な権限を持つメンバーに相談してください。",
"auth.permissionHint.title": "認可を設定する権限がありません。",
"auth.personal": "個人的な",
"auth.saveAndAuth": "保存と承認",
"auth.saveOnly": "保存のみ",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "OAuth 클라이언트 설정",
"auth.onlyAtCreationHint": "전환 후에는 다시 선택할 수 없습니다",
"auth.onlyAtCreationHintTooltip": "다른 구성원이 구성 · 전환 후 다시 선택할 수 없습니다.",
"auth.permissionHint.action": "누가 도와줄 수 있나요?",
"auth.permissionHint.description": "플러그인 인증은 워크스페이스 전체에서 공유됩니다. 필요한 권한이 있는 멤버에게 도움을 요청하세요.",
"auth.permissionHint.title": "인증을 구성할 권한이 없습니다.",
"auth.personal": "개인",
"auth.saveAndAuth": "저장하고 승인하세요",
"auth.saveOnly": "저장만 하기",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "OAuth Client Settings",
"auth.onlyAtCreationHint": "Na overschakeling niet meer selecteerbaar",
"auth.onlyAtCreationHintTooltip": "Geconfigureerd door andere leden · Kan na het overstappen niet meer geselecteerd worden.",
"auth.permissionHint.action": "Wie kan helpen?",
"auth.permissionHint.description": "Plugin-autorisatie wordt gedeeld in de hele workspace. Neem contact op met een lid met de vereiste rechten voor hulp.",
"auth.permissionHint.title": "Je hebt geen toestemming om autorisatie te configureren.",
"auth.personal": "Persoonlijk",
"auth.saveAndAuth": "Save and Authorize",
"auth.saveOnly": "Save only",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "Ustawienia klienta OAuth",
"auth.onlyAtCreationHint": "Po przełączeniu nie można wybrać ponownie",
"auth.onlyAtCreationHintTooltip": "Skonfigurowane przez innych użytkowników · Nie można wybrać ponownie po przełączeniu.",
"auth.permissionHint.action": "Kto może pomóc?",
"auth.permissionHint.description": "Autoryzacja wtyczki jest współdzielona w całym workspace. Skontaktuj się z członkiem mającym wymagane uprawnienia.",
"auth.permissionHint.title": "Nie masz uprawnień do konfiguracji autoryzacji.",
"auth.personal": "Osobiste",
"auth.saveAndAuth": "Zapisz i autoryzuj",
"auth.saveOnly": "Zapisz tylko",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "Configurações do Cliente OAuth",
"auth.onlyAtCreationHint": "Não pode ser selecionado novamente após a troca",
"auth.onlyAtCreationHintTooltip": "Configurado por outros membros · Não pode ser selecionado novamente após a troca.",
"auth.permissionHint.action": "Quem pode ajudar?",
"auth.permissionHint.description": "A autorização do plugin é compartilhada em todo o workspace. Entre em contato com um membro com as permissões necessárias para obter ajuda.",
"auth.permissionHint.title": "Você não tem permissão para configurar a autorização.",
"auth.personal": "Pessoal",
"auth.saveAndAuth": "Salvar e Autorizar",
"auth.saveOnly": "Salvar apenas",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "Setările clientului OAuth",
"auth.onlyAtCreationHint": "Nu poate fi selectat din nou după comutare",
"auth.onlyAtCreationHintTooltip": "Configurat de alți membri · Nu poate fi selectat din nou după comutare.",
"auth.permissionHint.action": "Cine poate ajuta?",
"auth.permissionHint.description": "Autorizarea pluginului este partajată în întregul workspace. Contactează un membru cu permisiunile necesare pentru ajutor.",
"auth.permissionHint.title": "Nu ai permisiunea de a configura autorizarea.",
"auth.personal": "Personalizat",
"auth.saveAndAuth": "Salvează și Autorizează",
"auth.saveOnly": "Salvează doar",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "Настройки клиента OAuth",
"auth.onlyAtCreationHint": "Невозможно выбрать снова после переключения",
"auth.onlyAtCreationHintTooltip": "Настроено другими участниками · Невозможно выбрать повторно после переключения.",
"auth.permissionHint.action": "Кто может помочь?",
"auth.permissionHint.description": "Авторизация плагина действует для всего рабочего пространства. Обратитесь за помощью к участнику с нужными правами.",
"auth.permissionHint.title": "У вас нет разрешения на настройку авторизации.",
"auth.personal": "Персональный",
"auth.saveAndAuth": "Сохранить и авторизовать",
"auth.saveOnly": "Сохранить только",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "Nastavitve odjemalca OAuth",
"auth.onlyAtCreationHint": "Po preklopu ga ni mogoče znova izbrati",
"auth.onlyAtCreationHintTooltip": "Konfigurirali drugi člani · Po zamenjavi ni mogoče znova izbrati.",
"auth.permissionHint.action": "Kdo lahko pomaga?",
"auth.permissionHint.description": "Avtorizacija vtičnika je v skupni rabi v celotnem workspaceu. Za pomoč se obrnite na člana z zahtevanimi dovoljenji.",
"auth.permissionHint.title": "Nimate dovoljenja za konfiguracijo avtorizacije.",
"auth.personal": "Osebno",
"auth.saveAndAuth": "Shrani in pooblasti",
"auth.saveOnly": "Shrani samo",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "การตั้งค่าไคลเอนต์ OAuth",
"auth.onlyAtCreationHint": "ไม่สามารถเลือกได้อีกหลังจากเปลี่ยนแล้ว",
"auth.onlyAtCreationHintTooltip": "กำหนดค่าโดยสมาชิกรายอื่น · ไม่สามารถเลือกได้อีกหลังจากเปลี่ยนแล้ว",
"auth.permissionHint.action": "ใครช่วยได้บ้าง?",
"auth.permissionHint.description": "การอนุญาตของปลั๊กอินใช้ร่วมกันทั้ง workspace ติดต่อสมาชิกที่มีสิทธิ์ที่จำเป็นเพื่อขอความช่วยเหลือ",
"auth.permissionHint.title": "คุณไม่มีสิทธิ์กำหนดค่าการอนุญาต",
"auth.personal": "ส่วนตัว",
"auth.saveAndAuth": "บันทึกและอนุญาต",
"auth.saveOnly": "บันทึกเฉพาะ",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "OAuth İstemci Ayarları",
"auth.onlyAtCreationHint": "Geçişten sonra tekrar seçilemez",
"auth.onlyAtCreationHintTooltip": "Diğer üyeler tarafından yapılandırıldı · Geçişten sonra tekrar seçilemez.",
"auth.permissionHint.action": "Kim yardımcı olabilir?",
"auth.permissionHint.description": "Eklenti yetkilendirmesi tüm workspace genelinde paylaşılır. Yardım için gerekli izinlere sahip bir üyeyle iletişime geçin.",
"auth.permissionHint.title": "Yetkilendirmeyi yapılandırma izniniz yok.",
"auth.personal": "Kişisel",
"auth.saveAndAuth": "Kaydet ve Yetkilendir",
"auth.saveOnly": "Sadece kaydet",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "Налаштування клієнта OAuth",
"auth.onlyAtCreationHint": "Не можна вибрати знову після перемикання",
"auth.onlyAtCreationHintTooltip": "Налаштовано іншими учасниками · Неможливо вибрати знову після перемикання.",
"auth.permissionHint.action": "Хто може допомогти?",
"auth.permissionHint.description": "Авторизація плагіна спільна для всього workspace. Зверніться по допомогу до учасника з потрібними дозволами.",
"auth.permissionHint.title": "У вас немає дозволу налаштовувати авторизацію.",
"auth.personal": "Особистий",
"auth.saveAndAuth": "Зберегти та авторизувати",
"auth.saveOnly": "Зберегти лише",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "Cài đặt khách hàng OAuth",
"auth.onlyAtCreationHint": "Không thể chọn lại sau khi chuyển đổi",
"auth.onlyAtCreationHintTooltip": "Được cấu hình bởi các thành viên khác. Không thể chọn lại sau khi chuyển đổi.",
"auth.permissionHint.action": "Ai có thể giúp?",
"auth.permissionHint.description": "Ủy quyền plugin được chia sẻ trong toàn bộ workspace. Liên hệ với thành viên có quyền cần thiết để được trợ giúp.",
"auth.permissionHint.title": "Bạn không có quyền cấu hình ủy quyền.",
"auth.personal": "Riêng tư",
"auth.saveAndAuth": "Lưu và Xác nhận",
"auth.saveOnly": "Chỉ lưu lại",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "OAuth 客户端设置",
"auth.onlyAtCreationHint": "切换后不可再选回",
"auth.onlyAtCreationHintTooltip": "由其他成员配置 · 切换后不可再选回",
"auth.permissionHint.action": "谁可以帮忙?",
"auth.permissionHint.description": "插件授权在整个工作区共享。请联系拥有所需权限的成员获取帮助。",
"auth.permissionHint.title": "你没有配置授权的权限。",
"auth.personal": "个人",
"auth.saveAndAuth": "保存并授权",
"auth.saveOnly": "仅保存",

View File

@ -26,6 +26,9 @@
"auth.oauthClientSettings": "OAuth 客戶端設置",
"auth.onlyAtCreationHint": "切換後無法再次選擇",
"auth.onlyAtCreationHintTooltip": "由其他成員配置 · 切換後無法再次選擇。",
"auth.permissionHint.action": "誰可以幫忙?",
"auth.permissionHint.description": "外掛授權會在整個工作區共用。請聯絡擁有所需權限的成員取得協助。",
"auth.permissionHint.title": "你沒有設定授權的權限。",
"auth.personal": "個人的",
"auth.saveAndAuth": "保存並授權",
"auth.saveOnly": "僅保存",