From 57abd46320f6b6653adcac95263118ae7e00808d Mon Sep 17 00:00:00 2001 From: Kathir Eswaran Date: Wed, 5 Aug 2026 16:59:52 +0530 Subject: [PATCH] fix(core): localize organization invitation validation errors --- .changeset/org-invitation-error-i18n.md | 7 +++++ .../src/libraries/organization-invitation.ts | 11 +++----- .../routes/organization-invitation/index.ts | 7 ++--- .../organization-invitation.creation.test.ts | 4 +-- .../organization-invitation.status.test.ts | 27 ++++++++++++++++--- .../src/locales/ar/errors/organization.ts | 6 +++++ .../src/locales/de/errors/organization.ts | 6 +++++ .../src/locales/en/errors/organization.ts | 5 ++++ .../src/locales/es/errors/organization.ts | 6 +++++ .../src/locales/fa-ir/errors/organization.ts | 5 ++++ .../src/locales/fr/errors/organization.ts | 7 +++++ .../src/locales/it/errors/organization.ts | 5 ++++ .../src/locales/ja/errors/organization.ts | 6 +++++ .../src/locales/ko/errors/organization.ts | 6 +++++ .../src/locales/pl-pl/errors/organization.ts | 6 +++++ .../src/locales/pt-br/errors/organization.ts | 5 ++++ .../src/locales/pt-pt/errors/organization.ts | 5 ++++ .../src/locales/ru/errors/organization.ts | 6 +++++ .../src/locales/th/errors/organization.ts | 5 ++++ .../src/locales/tr-tr/errors/organization.ts | 6 +++++ .../src/locales/zh-cn/errors/organization.ts | 5 ++++ .../src/locales/zh-hk/errors/organization.ts | 5 ++++ .../src/locales/zh-tw/errors/organization.ts | 5 ++++ 23 files changed, 139 insertions(+), 17 deletions(-) create mode 100644 .changeset/org-invitation-error-i18n.md diff --git a/.changeset/org-invitation-error-i18n.md b/.changeset/org-invitation-error-i18n.md new file mode 100644 index 000000000000..b1083b927636 --- /dev/null +++ b/.changeset/org-invitation-error-i18n.md @@ -0,0 +1,7 @@ +--- +'@logto/core': minor +--- + +use dedicated i18n error codes for organization invitation validation errors + +Organization invitation creation and status update errors previously returned the generic `request.invalid_input` code with English-only `details`. They now return specific, localized codes under the `organization` namespace: `invitee_already_member`, `expires_at_in_future`, `invitation_status_not_changeable`, `accepted_user_id_required`, and `accepted_user_email_mismatch`, so clients can reliably distinguish each failure case and messages render in the user's language. diff --git a/packages/core/src/libraries/organization-invitation.ts b/packages/core/src/libraries/organization-invitation.ts index 009a38ebfada..c1d7064ad6a9 100644 --- a/packages/core/src/libraries/organization-invitation.ts +++ b/packages/core/src/libraries/organization-invitation.ts @@ -68,8 +68,7 @@ export class OrganizationInvitationLibrary { if (await this.queries.organizations.relations.users.isMember(organizationId, invitee)) { throw new RequestError({ status: 422, - code: 'request.invalid_input', - details: 'The invitee is already a member of the organization.', + code: 'organization.invitee_already_member', }); } @@ -152,7 +151,7 @@ export class OrganizationInvitationLibrary { status: OrganizationInvitationStatus.Accepted, acceptedUserId: string ): Promise; - // TODO: Error i18n + async updateStatus( id: string, status: OrganizationInvitationStatus, @@ -163,8 +162,7 @@ export class OrganizationInvitationLibrary { if (endingStatuses.includes(entity.status)) { throw new RequestError({ status: 422, - code: 'request.invalid_input', - details: 'The status of the invitation cannot be changed anymore.', + code: 'organization.invitation_status_not_changeable', }); } @@ -184,8 +182,7 @@ export class OrganizationInvitationLibrary { if (user.primaryEmail?.toLowerCase() !== entity.invitee.toLowerCase()) { throw new RequestError({ status: 422, - code: 'request.invalid_input', - details: 'The accepted user must have the same email as the invitee.', + code: 'organization.accepted_user_email_mismatch', }); } diff --git a/packages/core/src/routes/organization-invitation/index.ts b/packages/core/src/routes/organization-invitation/index.ts index 7f2a51cbe9f3..5df07414917e 100644 --- a/packages/core/src/routes/organization-invitation/index.ts +++ b/packages/core/src/routes/organization-invitation/index.ts @@ -77,8 +77,7 @@ export default function organizationInvitationRoutes Date.now(), new RequestError({ - code: 'request.invalid_input', - details: 'The value of `expiresAt` must be in the future.', + code: 'organization.expires_at_in_future', }) ); @@ -149,13 +148,11 @@ export default function organizationInvitationRoutes { }) .catch((error: unknown) => error); - await expectErrorResponse(error, 400, 'request.invalid_input'); + await expectErrorResponse(error, 400, 'organization.expires_at_in_future'); }); it('should not be able to create invitations if the invitee is already a member of the organization', async () => { @@ -172,7 +172,7 @@ describe('organization invitation creation', () => { }) .catch((error: unknown) => error); - await expectErrorResponse(error, 422, 'request.invalid_input'); + await expectErrorResponse(error, 422, 'organization.invitee_already_member'); }); it('should not be able to create invitations with an invalid email', async () => { diff --git a/packages/integration-tests/src/tests/api/organization/organization-invitation.status.test.ts b/packages/integration-tests/src/tests/api/organization/organization-invitation.status.test.ts index 9ce6b2658864..d48915740916 100644 --- a/packages/integration-tests/src/tests/api/organization/organization-invitation.status.test.ts +++ b/packages/integration-tests/src/tests/api/organization/organization-invitation.status.test.ts @@ -48,7 +48,7 @@ describe('organization invitation status update', () => { const error = await invitationApi .updateStatus(invitation.id, OrganizationInvitationStatus.Accepted) .catch((error: unknown) => error); - await expectErrorResponse(error, 422, 'request.invalid_input'); + await expectErrorResponse(error, 422, 'organization.accepted_user_id_required'); }); it('should be able to accept an invitation', async () => { @@ -128,7 +128,7 @@ describe('organization invitation status update', () => { .updateStatus(invitation.id, OrganizationInvitationStatus.Accepted, user.id) .catch((error: unknown) => error); - await expectErrorResponse(error, 422, 'request.invalid_input'); + await expectErrorResponse(error, 422, 'organization.accepted_user_email_mismatch'); }); it('should not be able to accept an invitation with an invalid user id', async () => { @@ -162,6 +162,27 @@ describe('organization invitation status update', () => { .updateStatus(invitation.id, OrganizationInvitationStatus.Accepted) .catch((error: unknown) => error); - await expectErrorResponse(error, 422, 'request.invalid_input'); + await expectErrorResponse(error, 422, 'organization.accepted_user_id_required'); + }); + + it('should not be able to update the status of an accepted invitation', async () => { + const organization = await organizationApi.create({ name: 'test' }); + const invitation = await invitationApi.create({ + organizationId: organization.id, + invitee: `${randomId()}@example.com`, + expiresAt: Date.now() + 1_000_000, + }); + expect(invitation.status).toBe('Pending'); + + const user = await userApi.create({ + primaryEmail: invitation.invitee, + }); + await invitationApi.updateStatus(invitation.id, OrganizationInvitationStatus.Accepted, user.id); + + const error = await invitationApi + .updateStatus(invitation.id, OrganizationInvitationStatus.Revoked) + .catch((error: unknown) => error); + + await expectErrorResponse(error, 422, 'organization.invitation_status_not_changeable'); }); }); diff --git a/packages/phrases/src/locales/ar/errors/organization.ts b/packages/phrases/src/locales/ar/errors/organization.ts index ed3a592d0455..7f91d48fee24 100644 --- a/packages/phrases/src/locales/ar/errors/organization.ts +++ b/packages/phrases/src/locales/ar/errors/organization.ts @@ -2,6 +2,12 @@ const organization = { require_membership: 'يجب أن يكون المستخدم عضوًا في المنظمة للمتابعة.', role_names_not_found: 'تم اكتشاف أسماء أدوار غير صالحة: {{names,list(type:conjunction)}}. يُرجى إنشاء هذه الأدوار أولاً قبل المتابعة.', + invitation_status_not_changeable: 'لا يمكن تغيير حالة الدعوة بعد الآن.', + accepted_user_id_required: '`acceptedUserId` مطلوب عند قبول دعوة.', + invitee_already_member: 'المدعو عضو بالفعل في المنظمة.', + accepted_user_email_mismatch: + 'يجب أن يكون للمستخدم الذي يقبل الدعوة نفس البريد الإلكتروني الخاص بالمدعو.', + expires_at_in_future: 'يجب أن تكون قيمة `expiresAt` في المستقبل.', }; export default Object.freeze(organization); diff --git a/packages/phrases/src/locales/de/errors/organization.ts b/packages/phrases/src/locales/de/errors/organization.ts index e621744f319d..537a03e5c0ba 100644 --- a/packages/phrases/src/locales/de/errors/organization.ts +++ b/packages/phrases/src/locales/de/errors/organization.ts @@ -2,6 +2,12 @@ const organization = { require_membership: 'Der Benutzer muss Mitglied der Organisation sein, um fortzufahren.', role_names_not_found: 'Ungültige Rollennamen erkannt: {{names,list(type:conjunction)}}. Bitte erstelle diese Rollen zuerst, bevor du fortfährst.', + invitation_status_not_changeable: 'Der Status der Einladung kann nicht mehr geändert werden.', + accepted_user_id_required: 'Die `acceptedUserId` ist beim Annehmen einer Einladung erforderlich.', + invitee_already_member: 'Der Eingeladene ist bereits Mitglied der Organisation.', + accepted_user_email_mismatch: + 'Der annehmende Benutzer muss dieselbe E-Mail-Adresse wie der Eingeladene haben.', + expires_at_in_future: 'Der Wert von `expiresAt` muss in der Zukunft liegen.', }; export default Object.freeze(organization); diff --git a/packages/phrases/src/locales/en/errors/organization.ts b/packages/phrases/src/locales/en/errors/organization.ts index 2cb49171f652..7261f7488758 100644 --- a/packages/phrases/src/locales/en/errors/organization.ts +++ b/packages/phrases/src/locales/en/errors/organization.ts @@ -2,6 +2,11 @@ const organizations = { require_membership: 'The user must be a member of the organization to proceed.', role_names_not_found: 'Invalid role names detected: {{names,list(type:conjunction)}}. Please create these roles first before proceeding.', + invitation_status_not_changeable: 'The status of the invitation cannot be changed anymore.', + accepted_user_id_required: 'The `acceptedUserId` is required when accepting an invitation.', + invitee_already_member: 'The invitee is already a member of the organization.', + accepted_user_email_mismatch: 'The accepted user must have the same email as the invitee.', + expires_at_in_future: 'The value of `expiresAt` must be in the future.', }; export default Object.freeze(organizations); diff --git a/packages/phrases/src/locales/es/errors/organization.ts b/packages/phrases/src/locales/es/errors/organization.ts index 0f3eba6687dc..9e0e153dadce 100644 --- a/packages/phrases/src/locales/es/errors/organization.ts +++ b/packages/phrases/src/locales/es/errors/organization.ts @@ -2,6 +2,12 @@ const organization = { require_membership: 'El usuario debe ser miembro de la organización para continuar.', role_names_not_found: 'Nombres de roles no válidos detectados: {{names,list(type:conjunction)}}. Por favor, crea estos roles primero antes de continuar.', + invitation_status_not_changeable: 'El estado de la invitación ya no se puede cambiar.', + accepted_user_id_required: 'Se requiere `acceptedUserId` al aceptar una invitación.', + invitee_already_member: 'El invitado ya es miembro de la organización.', + accepted_user_email_mismatch: + 'El usuario que acepta debe tener el mismo correo electrónico que el invitado.', + expires_at_in_future: 'El valor de `expiresAt` debe estar en el futuro.', }; export default Object.freeze(organization); diff --git a/packages/phrases/src/locales/fa-ir/errors/organization.ts b/packages/phrases/src/locales/fa-ir/errors/organization.ts index 80130c4847ec..c3c32931d9a5 100644 --- a/packages/phrases/src/locales/fa-ir/errors/organization.ts +++ b/packages/phrases/src/locales/fa-ir/errors/organization.ts @@ -2,6 +2,11 @@ const organizations = { require_membership: 'کاربر باید عضو سازمان باشد تا ادامه دهد.', role_names_not_found: 'نام‌های نقش نامعتبر شناسایی شد: {{names,list(type:conjunction)}}. لطفاً ابتدا این نقش‌ها را ایجاد کنید.', + invitation_status_not_changeable: 'وضعیت دعوت‌نامه دیگر قابل تغییر نیست.', + accepted_user_id_required: 'هنگام پذیرش دعوت‌نامه، `acceptedUserId` الزامی است.', + invitee_already_member: 'دعوت‌شونده در حال حاضر عضو سازمان است.', + accepted_user_email_mismatch: 'کاربر پذیرنده باید همان ایمیل دعوت‌شونده را داشته باشد.', + expires_at_in_future: 'مقدار `expiresAt` باید در آینده باشد.', }; export default Object.freeze(organizations); diff --git a/packages/phrases/src/locales/fr/errors/organization.ts b/packages/phrases/src/locales/fr/errors/organization.ts index a2df80c5905c..8838884a7ed2 100644 --- a/packages/phrases/src/locales/fr/errors/organization.ts +++ b/packages/phrases/src/locales/fr/errors/organization.ts @@ -2,6 +2,13 @@ const organization = { require_membership: "L'utilisateur doit être membre de l'organisation pour continuer.", role_names_not_found: "Des noms de rôles non valides ont été détectés : {{names,list(type:conjunction)}}. Veuillez créer ces rôles d'abord avant de continuer.", + invitation_status_not_changeable: "Le statut de l'invitation ne peut plus être modifié.", + accepted_user_id_required: + "L'`acceptedUserId` est requis lors de l'acceptation d'une invitation.", + invitee_already_member: "L'invité est déjà membre de l'organisation.", + accepted_user_email_mismatch: + "L'utilisateur qui accepte doit avoir la même adresse e-mail que l'invité.", + expires_at_in_future: 'La valeur de `expiresAt` doit être dans le futur.', }; export default Object.freeze(organization); diff --git a/packages/phrases/src/locales/it/errors/organization.ts b/packages/phrases/src/locales/it/errors/organization.ts index 208b245b15d9..e19c5ce07faa 100644 --- a/packages/phrases/src/locales/it/errors/organization.ts +++ b/packages/phrases/src/locales/it/errors/organization.ts @@ -2,6 +2,11 @@ const organization = { require_membership: "L'utente deve essere un membro dell'organizzazione per procedere.", role_names_not_found: 'Nomi di ruoli non validi rilevati: {{names,list(type:conjunction)}}. Si prega di creare prima questi ruoli prima di procedere.', + invitation_status_not_changeable: "Lo stato dell'invito non può più essere modificato.", + accepted_user_id_required: "L'`acceptedUserId` è obbligatorio quando si accetta un invito.", + invitee_already_member: "L'invitato è già membro dell'organizzazione.", + accepted_user_email_mismatch: "L'utente che accetta deve avere la stessa email dell'invitato.", + expires_at_in_future: 'Il valore di `expiresAt` deve essere nel futuro.', }; export default Object.freeze(organization); diff --git a/packages/phrases/src/locales/ja/errors/organization.ts b/packages/phrases/src/locales/ja/errors/organization.ts index 72dd461034e1..d0e7ea9484d5 100644 --- a/packages/phrases/src/locales/ja/errors/organization.ts +++ b/packages/phrases/src/locales/ja/errors/organization.ts @@ -2,6 +2,12 @@ const organization = { require_membership: 'ユーザーは組織のメンバーである必要があります。', role_names_not_found: '無効なロール名が検出されました:{{names,list(type:conjunction)}}。これらのロールを作成してから次へ進んでください。', + invitation_status_not_changeable: '招待のステータスはこれ以上変更できません。', + accepted_user_id_required: '招待を受け入れるには `acceptedUserId` が必要です。', + invitee_already_member: '招待されたユーザーはすでに組織のメンバーです。', + accepted_user_email_mismatch: + '受け入れるユーザーは招待されたユーザーと同じメールアドレスである必要があります。', + expires_at_in_future: '`expiresAt` の値は将来である必要があります。', }; export default Object.freeze(organization); diff --git a/packages/phrases/src/locales/ko/errors/organization.ts b/packages/phrases/src/locales/ko/errors/organization.ts index c3b4045826e3..7e74da63aa60 100644 --- a/packages/phrases/src/locales/ko/errors/organization.ts +++ b/packages/phrases/src/locales/ko/errors/organization.ts @@ -2,6 +2,12 @@ const organization = { require_membership: '사용자는 조직의 구성원이어야 합니다.', role_names_not_found: '유효하지 않은 역할 이름이 감지되었습니다: {{names,list(type:conjunction)}}. 계속하기 전에 먼저 이 역할들을 생성해 주세요.', + invitation_status_not_changeable: '초대 상태는 더 이상 변경할 수 없습니다.', + accepted_user_id_required: '초대를 수락하려면 `acceptedUserId`가 필요합니다.', + invitee_already_member: '초대받은 사용자는 이미 조직의 구성원입니다.', + accepted_user_email_mismatch: + '수락하는 사용자는 초대받은 사용자와 동일한 이메일을 가져야 합니다.', + expires_at_in_future: '`expiresAt` 값은 미래여야 합니다.', }; export default Object.freeze(organization); diff --git a/packages/phrases/src/locales/pl-pl/errors/organization.ts b/packages/phrases/src/locales/pl-pl/errors/organization.ts index d40ff7602155..32e875b6433f 100644 --- a/packages/phrases/src/locales/pl-pl/errors/organization.ts +++ b/packages/phrases/src/locales/pl-pl/errors/organization.ts @@ -2,6 +2,12 @@ const organization = { require_membership: 'Użytkownik musi być członkiem organizacji, aby kontynuować.', role_names_not_found: '检测到无效的角色名称:{{names,list(type:conjunction)}}。请先创建这些角色,然后再继续。', + invitation_status_not_changeable: 'Status zaproszenia nie może być już zmieniony.', + accepted_user_id_required: '`acceptedUserId` jest wymagane podczas akceptowania zaproszenia.', + invitee_already_member: 'Zaproszony użytkownik jest już członkiem organizacji.', + accepted_user_email_mismatch: + 'Akceptujący użytkownik musi mieć ten sam adres e-mail co zaproszony.', + expires_at_in_future: 'Wartość `expiresAt` musi być w przyszłości.', }; export default Object.freeze(organization); diff --git a/packages/phrases/src/locales/pt-br/errors/organization.ts b/packages/phrases/src/locales/pt-br/errors/organization.ts index ee4c275db823..320ba9a5c15f 100644 --- a/packages/phrases/src/locales/pt-br/errors/organization.ts +++ b/packages/phrases/src/locales/pt-br/errors/organization.ts @@ -2,6 +2,11 @@ const organization = { require_membership: 'O usuário deve ser um membro da organização para continuar.', role_names_not_found: '检测到无效的角色名称:{{names,list(type:conjunction)}}。请先创建这些角色然后再继续操作。', + invitation_status_not_changeable: 'O status do convite não pode mais ser alterado.', + accepted_user_id_required: 'O `acceptedUserId` é obrigatório ao aceitar um convite.', + invitee_already_member: 'O convidado já é membro da organização.', + accepted_user_email_mismatch: 'O usuário que aceita deve ter o mesmo e-mail do convidado.', + expires_at_in_future: 'O valor de `expiresAt` deve estar no futuro.', }; export default Object.freeze(organization); diff --git a/packages/phrases/src/locales/pt-pt/errors/organization.ts b/packages/phrases/src/locales/pt-pt/errors/organization.ts index 3a31d9fcc71a..5f562db1070c 100644 --- a/packages/phrases/src/locales/pt-pt/errors/organization.ts +++ b/packages/phrases/src/locales/pt-pt/errors/organization.ts @@ -2,6 +2,11 @@ const organization = { require_membership: 'O utilizador deve ser membro da organização para avançar.', role_names_not_found: '检测到无效的角色名称:{{names,list(type:conjunction)}}。请先创建这些角色然后再继续。', + invitation_status_not_changeable: 'O estado do convite já não pode ser alterado.', + accepted_user_id_required: 'O `acceptedUserId` é obrigatório ao aceitar um convite.', + invitee_already_member: 'O convidado já é membro da organização.', + accepted_user_email_mismatch: 'O utilizador que aceita deve ter o mesmo e-mail do convidado.', + expires_at_in_future: 'O valor de `expiresAt` deve estar no futuro.', }; export default Object.freeze(organization); diff --git a/packages/phrases/src/locales/ru/errors/organization.ts b/packages/phrases/src/locales/ru/errors/organization.ts index 93e79061fa3c..f6c365f35470 100644 --- a/packages/phrases/src/locales/ru/errors/organization.ts +++ b/packages/phrases/src/locales/ru/errors/organization.ts @@ -2,6 +2,12 @@ const organization = { require_membership: 'Пользователь должен быть участником организации, чтобы продолжить.', role_names_not_found: 'Обнаружены недопустимые имена ролей: {{names,list(type:conjunction)}}. Пожалуйста, сначала создайте эти роли, прежде чем продолжить.', + invitation_status_not_changeable: 'Статус приглашения больше не может быть изменен.', + accepted_user_id_required: '`acceptedUserId` обязателен при принятии приглашения.', + invitee_already_member: 'Приглашенный уже является участником организации.', + accepted_user_email_mismatch: + 'Принимающий пользователь должен иметь тот же адрес электронной почты, что и приглашенный.', + expires_at_in_future: 'Значение `expiresAt` должно быть в будущем.', }; export default Object.freeze(organization); diff --git a/packages/phrases/src/locales/th/errors/organization.ts b/packages/phrases/src/locales/th/errors/organization.ts index c81290b3d5c8..4c941d1a0b09 100644 --- a/packages/phrases/src/locales/th/errors/organization.ts +++ b/packages/phrases/src/locales/th/errors/organization.ts @@ -2,6 +2,11 @@ const organization = { require_membership: 'ผู้ใช้จะต้องเป็นสมาชิกขององค์กรก่อนจึงจะดำเนินการต่อได้', role_names_not_found: 'ตรวจพบชื่อบทบาทที่ไม่ถูกต้อง: {{names,list(type:conjunction)}} กรุณาสร้างบทบาทเหล่านี้ก่อนจึงจะดำเนินการต่อได้', + invitation_status_not_changeable: 'ไม่สามารถเปลี่ยนสถานะคำเชิญได้อีกต่อไป', + accepted_user_id_required: 'จำเป็นต้องระบุ `acceptedUserId` เมื่อยอมรับคำเชิญ', + invitee_already_member: 'ผู้ที่ได้รับเชิญเป็นสมาชิกขององค์กรอยู่แล้ว', + accepted_user_email_mismatch: 'ผู้ใช้ที่ยอมรับต้องมีอีเมลเดียวกับผู้ที่ได้รับเชิญ', + expires_at_in_future: 'ค่าของ `expiresAt` ต้องอยู่ในอนาคต', }; export default Object.freeze(organization); diff --git a/packages/phrases/src/locales/tr-tr/errors/organization.ts b/packages/phrases/src/locales/tr-tr/errors/organization.ts index 11a16109bd71..db6887d6c5af 100644 --- a/packages/phrases/src/locales/tr-tr/errors/organization.ts +++ b/packages/phrases/src/locales/tr-tr/errors/organization.ts @@ -2,6 +2,12 @@ const organization = { require_membership: 'Kullanıcının devam etmek için organizasyonun bir üyesi olması gerekir.', role_names_not_found: '检测到无效的角色名称:{{names,list(type:conjunction)}}。请先创建这些角色,然后再继续。', + invitation_status_not_changeable: 'Davetin durumu artık değiştirilemez.', + accepted_user_id_required: 'Bir daveti kabul ederken `acceptedUserId` gerekli.', + invitee_already_member: 'Davet edilen kişi zaten organizasyonun bir üyesi.', + accepted_user_email_mismatch: + 'Kabul eden kullanıcının, davet edilenle aynı e-postaya sahip olması gerekir.', + expires_at_in_future: '`expiresAt` değeri gelecekte olmalıdır.', }; export default Object.freeze(organization); diff --git a/packages/phrases/src/locales/zh-cn/errors/organization.ts b/packages/phrases/src/locales/zh-cn/errors/organization.ts index ce80fc79a894..ff1067092256 100644 --- a/packages/phrases/src/locales/zh-cn/errors/organization.ts +++ b/packages/phrases/src/locales/zh-cn/errors/organization.ts @@ -2,6 +2,11 @@ const organization = { require_membership: '用户必须是组织的成员才能继续。', role_names_not_found: '检测到无效的角色名称:{{names,list(type:conjunction)}}。请先创建这些角色,然后再继续。', + invitation_status_not_changeable: '邀请状态不能再更改。', + accepted_user_id_required: '接受邀请时必须提供 `acceptedUserId`。', + invitee_already_member: '受邀者已经是该组织的成员。', + accepted_user_email_mismatch: '接受邀请的用户必须与受邀者邮箱一致。', + expires_at_in_future: '`expiresAt` 的值必须在未来。', }; export default Object.freeze(organization); diff --git a/packages/phrases/src/locales/zh-hk/errors/organization.ts b/packages/phrases/src/locales/zh-hk/errors/organization.ts index f4d501ab95b2..94f1a8f6941c 100644 --- a/packages/phrases/src/locales/zh-hk/errors/organization.ts +++ b/packages/phrases/src/locales/zh-hk/errors/organization.ts @@ -2,6 +2,11 @@ const organization = { require_membership: '用戶必須是組織的成員才能繼續。', role_names_not_found: '檢測到無效的角色名稱:{{names,list(type:conjunction)}}。請先創建這些角色再繼續。', + invitation_status_not_changeable: '邀請狀態不能再更改。', + accepted_user_id_required: '接受邀請時必須提供 `acceptedUserId`。', + invitee_already_member: '受邀者已經是該組織的成員。', + accepted_user_email_mismatch: '接受邀請的用戶必須與受邀者電郵一致。', + expires_at_in_future: '`expiresAt` 的值必須在未來。', }; export default Object.freeze(organization); diff --git a/packages/phrases/src/locales/zh-tw/errors/organization.ts b/packages/phrases/src/locales/zh-tw/errors/organization.ts index 34e3c58d0329..5740ab3bf14f 100644 --- a/packages/phrases/src/locales/zh-tw/errors/organization.ts +++ b/packages/phrases/src/locales/zh-tw/errors/organization.ts @@ -2,6 +2,11 @@ const organization = { require_membership: '使用者必須是該組織的成員才能繼續。', role_names_not_found: '检测到无效的角色名称:{{names,list(type:conjunction)}}。请先创建这些角色,然后再继续。', + invitation_status_not_changeable: '邀請狀態不能再更改。', + accepted_user_id_required: '接受邀請時必須提供 `acceptedUserId`。', + invitee_already_member: '受邀者已經是該組織的成員。', + accepted_user_email_mismatch: '接受邀請的使用者必須與受邀者電子郵件一致。', + expires_at_in_future: '`expiresAt` 的值必須在未來。', }; export default Object.freeze(organization);