mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 08:13:50 +00:00
fix: ask "discard changes?" with keep editing and discard in settings editors and the admin pages, as in calendar and contacts
This commit is contained in:
@@ -21,27 +21,27 @@ describe('admin unsaved changes guard (#1255)', () => {
|
||||
expect(screen.queryByRole('alertdialog')).toBeNull();
|
||||
});
|
||||
|
||||
it('asks before leaving with unsaved edits; Stay keeps the admin on the page', () => {
|
||||
it('asks before leaving with unsaved edits; Keep editing keeps the admin on the page', () => {
|
||||
render(<><UnsavedChangesGuard /><DirtySection dirty /></>);
|
||||
const action = vi.fn();
|
||||
act(() => useAdminUnsavedStore.getState().requestLeave(action));
|
||||
expect(screen.getByRole('alertdialog')).toBeTruthy();
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Stay' }));
|
||||
expect(screen.getByRole('alertdialog', { name: 'Discard changes?' })).toBeTruthy();
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Keep editing' }));
|
||||
expect(action).not.toHaveBeenCalled();
|
||||
expect(screen.queryByRole('alertdialog')).toBeNull();
|
||||
expect(useAdminUnsavedStore.getState().dirty).toEqual({ settings: true });
|
||||
});
|
||||
|
||||
it('Leave runs the action and drops the unsaved flag', () => {
|
||||
it('Discard runs the action and drops the unsaved flag', () => {
|
||||
render(<><UnsavedChangesGuard /><DirtySection dirty /></>);
|
||||
const action = vi.fn();
|
||||
act(() => useAdminUnsavedStore.getState().requestLeave(action));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Leave' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Discard' }));
|
||||
expect(action).toHaveBeenCalledTimes(1);
|
||||
expect(useAdminUnsavedStore.getState().dirty).toEqual({});
|
||||
});
|
||||
|
||||
it('Escape closes the prompt like Stay', () => {
|
||||
it('Escape closes the prompt like Keep editing', () => {
|
||||
render(<><UnsavedChangesGuard /><DirtySection dirty /></>);
|
||||
const action = vi.fn();
|
||||
act(() => useAdminUnsavedStore.getState().requestLeave(action));
|
||||
@@ -58,12 +58,12 @@ describe('admin unsaved changes guard (#1255)', () => {
|
||||
|
||||
act(() => useAdminUnsavedStore.getState().setDirty('plugin-config', true));
|
||||
act(() => useAdminUnsavedStore.getState().requestLeave(back, 'plugin-config'));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Leave' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Discard' }));
|
||||
expect(back).toHaveBeenCalledTimes(2);
|
||||
expect(useAdminUnsavedStore.getState().dirty).toEqual({ plugins: true });
|
||||
});
|
||||
|
||||
it('holds a link click until the admin picks Leave', () => {
|
||||
it('holds a link click until the admin picks Discard', () => {
|
||||
const onLinkClick = vi.fn((e: React.MouseEvent) => e.preventDefault());
|
||||
render(
|
||||
<>
|
||||
@@ -76,7 +76,7 @@ describe('admin unsaved changes guard (#1255)', () => {
|
||||
expect(onLinkClick).not.toHaveBeenCalled();
|
||||
expect(screen.getByRole('alertdialog')).toBeTruthy();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Leave' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Discard' }));
|
||||
expect(onLinkClick).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
@@ -103,7 +103,7 @@ describe('admin unsaved changes guard on Back', () => {
|
||||
await act(async () => { await done; });
|
||||
};
|
||||
|
||||
it('keeps the page and asks when Back is pressed with unsaved edits; Stay keeps guarding', async () => {
|
||||
it('keeps the page and asks when Back is pressed with unsaved edits; Keep editing keeps guarding', async () => {
|
||||
window.history.pushState(null, '', '/admin/policy');
|
||||
window.history.pushState(null, '', '/admin/telemetry');
|
||||
render(<><UnsavedChangesGuard /><DirtySection dirty /></>);
|
||||
@@ -112,7 +112,7 @@ describe('admin unsaved changes guard on Back', () => {
|
||||
expect(window.location.pathname).toBe('/admin/telemetry');
|
||||
expect(screen.getByRole('alertdialog')).toBeTruthy();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Stay' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Keep editing' }));
|
||||
expect(useAdminUnsavedStore.getState().dirty).toEqual({ settings: true });
|
||||
|
||||
// Back asks again: the page is still guarded.
|
||||
@@ -121,14 +121,14 @@ describe('admin unsaved changes guard on Back', () => {
|
||||
expect(screen.getByRole('alertdialog')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Leave goes back to the previous page', async () => {
|
||||
it('Discard goes back to the previous page', async () => {
|
||||
window.history.pushState(null, '', '/admin/policy');
|
||||
window.history.pushState(null, '', '/admin/telemetry');
|
||||
render(<><UnsavedChangesGuard /><DirtySection dirty /></>);
|
||||
|
||||
await back();
|
||||
const done = popped();
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Leave' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Discard' }));
|
||||
await act(async () => { await done; });
|
||||
expect(window.location.pathname).toBe('/admin/policy');
|
||||
expect(useAdminUnsavedStore.getState().dirty).toEqual({});
|
||||
|
||||
@@ -49,8 +49,8 @@ export function UnsavedChangesGuard() {
|
||||
// Back and the back gesture are a same-document popstate (the pages switch
|
||||
// through pushState), which can't be cancelled. So while something is
|
||||
// unsaved a copy of the page's entry sits on top: Back only takes that
|
||||
// one off, the page stays, and the prompt asks. Stay puts the copy back;
|
||||
// Leave goes back past the page for real.
|
||||
// one off, the page stays, and the prompt asks. Keep editing puts the
|
||||
// copy back; Discard goes back past the page for real.
|
||||
// The mark on the page entry the copy was put on top of.
|
||||
const guard = useRef<string | null>(null);
|
||||
useEffect(() => {
|
||||
@@ -124,10 +124,10 @@ export function UnsavedChangesGuard() {
|
||||
isOpen={isOpen}
|
||||
onClose={cancelLeave}
|
||||
onConfirm={confirmLeave}
|
||||
title="Unsaved changes"
|
||||
message="You have changes that haven't been saved. If you leave now, they will be lost."
|
||||
cancelText="Stay"
|
||||
confirmText="Leave"
|
||||
title="Discard changes?"
|
||||
message="Your changes haven't been saved."
|
||||
cancelText="Keep editing"
|
||||
confirmText="Discard"
|
||||
variant="destructive"
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { readdirSync, readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import en from '@/locales/en/common.json';
|
||||
import { getByPath } from '../settings-search';
|
||||
|
||||
@@ -59,6 +61,31 @@ describe('settings wording', () => {
|
||||
expect(text('notifications.filters_saved')).toBe('Filters saved');
|
||||
});
|
||||
|
||||
// R5: every editor asks the same question with the same buttons, in every
|
||||
// language: Settings and Contacts say what Calendar says.
|
||||
it('asks "Discard changes?" with Keep editing / Discard everywhere', () => {
|
||||
expect(text('calendar.discard.title')).toBe('Discard changes?');
|
||||
const mismatches: string[] = [];
|
||||
for (const locale of readdirSync(join(process.cwd(), 'locales'))) {
|
||||
const messages = JSON.parse(readFileSync(join(process.cwd(), 'locales', locale, 'common.json'), 'utf8'));
|
||||
const ref = getByPath(messages, 'calendar.discard') as Record<string, string>;
|
||||
const expected: Record<string, string> = {
|
||||
'settings.discard_changes': ref.title,
|
||||
'settings.unsaved_changes': ref.message,
|
||||
'settings.keep_editing': ref.keep,
|
||||
'settings.discard': ref.confirm,
|
||||
'contacts.form.discard_title': ref.title,
|
||||
'contacts.form.discard_message': ref.message,
|
||||
'contacts.form.keep_editing': ref.keep,
|
||||
'contacts.form.discard': ref.confirm,
|
||||
};
|
||||
for (const [key, value] of Object.entries(expected)) {
|
||||
if (getByPath(messages, key) !== value) mismatches.push(`${locale} ${key}`);
|
||||
}
|
||||
}
|
||||
expect(mismatches).toEqual([]);
|
||||
});
|
||||
|
||||
it('does not repeat the debug section title as its only row', () => {
|
||||
expect(text('settings.advanced.debug_mode.toggle')).not.toBe(text('settings.advanced.debug_mode.label'));
|
||||
});
|
||||
|
||||
@@ -1118,8 +1118,8 @@
|
||||
"import_success": "تم استيراد الإعدادات بنجاح",
|
||||
"import_error": "فشل استيراد الإعدادات",
|
||||
"reset_confirm": "هل أنت متأكد أنك تريد إعادة تعيين جميع الإعدادات إلى الافتراضية؟",
|
||||
"unsaved_changes": "لديك تغييرات غير محفوظة",
|
||||
"discard_changes": "تجاهل التغييرات غير المحفوظة؟",
|
||||
"unsaved_changes": "لم يتم حفظ تغييراتك.",
|
||||
"discard_changes": "تجاهل التغييرات؟",
|
||||
"discard": "تجاهل",
|
||||
"keep_editing": "متابعة التعديل",
|
||||
"search_placeholder": "بحث في الإعدادات",
|
||||
|
||||
@@ -1118,8 +1118,8 @@
|
||||
"import_success": "Configuració importada correctament",
|
||||
"import_error": "No s'ha pogut importar la configuració",
|
||||
"reset_confirm": "Segur que voleu restablir tota la configuració als valors per defecte?",
|
||||
"unsaved_changes": "Teniu canvis sense desar",
|
||||
"discard_changes": "Voleu descartar els canvis sense desar?",
|
||||
"unsaved_changes": "Els canvis no s'han desat.",
|
||||
"discard_changes": "Voleu descartar els canvis?",
|
||||
"discard": "Descarta",
|
||||
"keep_editing": "Continua editant",
|
||||
"search_placeholder": "Cerca a la configuració",
|
||||
|
||||
@@ -1118,8 +1118,8 @@
|
||||
"import_success": "Nastavení bylo importováno",
|
||||
"import_error": "Import nastavení selhal",
|
||||
"reset_confirm": "Opravdu chcete obnovit výchozí nastavení?",
|
||||
"unsaved_changes": "Máte neuložené změny",
|
||||
"discard_changes": "Zahodit neuložené změny?",
|
||||
"unsaved_changes": "Vaše změny nebyly uloženy.",
|
||||
"discard_changes": "Zahodit změny?",
|
||||
"discard": "Zahodit",
|
||||
"keep_editing": "Pokračovat v úpravách",
|
||||
"tabs": {
|
||||
|
||||
@@ -1118,8 +1118,8 @@
|
||||
"import_success": "Indstillinger importeret succesfuldt",
|
||||
"import_error": "Kunne ikke importere indstillinger",
|
||||
"reset_confirm": "Er du sikker på, at du vil nulstille alle indstillinger til standard?",
|
||||
"unsaved_changes": "Du har ugemte ændringer",
|
||||
"discard_changes": "Kassér ugemte ændringer?",
|
||||
"unsaved_changes": "Dine ændringer er ikke gemt.",
|
||||
"discard_changes": "Kassér ændringer?",
|
||||
"discard": "Kassér",
|
||||
"keep_editing": "Fortsæt redigering",
|
||||
"search_placeholder": "Søg i indstillinger",
|
||||
|
||||
@@ -1118,7 +1118,7 @@
|
||||
"import_success": "Einstellungen erfolgreich importiert",
|
||||
"import_error": "Import der Einstellungen fehlgeschlagen",
|
||||
"reset_confirm": "Sind Sie sicher, dass Sie alle Einstellungen auf die Standardwerte zurücksetzen möchten?",
|
||||
"unsaved_changes": "Sie haben ungespeicherte Änderungen",
|
||||
"unsaved_changes": "Ihre Änderungen wurden noch nicht gespeichert.",
|
||||
"discard_changes": "Änderungen verwerfen?",
|
||||
"discard": "Verwerfen",
|
||||
"keep_editing": "Weiter bearbeiten",
|
||||
@@ -3468,7 +3468,7 @@
|
||||
"save": "Speichern",
|
||||
"cancel": "Abbrechen",
|
||||
"discard_title": "Änderungen verwerfen?",
|
||||
"discard_message": "Ihre Änderungen wurden nicht gespeichert.",
|
||||
"discard_message": "Ihre Änderungen wurden noch nicht gespeichert.",
|
||||
"discard": "Verwerfen",
|
||||
"keep_editing": "Weiter bearbeiten",
|
||||
"remove_entry": "Entfernen",
|
||||
|
||||
@@ -1118,8 +1118,8 @@
|
||||
"import_success": "Settings imported",
|
||||
"import_error": "Couldn't import settings",
|
||||
"reset_confirm": "Are you sure you want to reset all settings to defaults?",
|
||||
"unsaved_changes": "You have unsaved changes",
|
||||
"discard_changes": "Discard unsaved changes?",
|
||||
"unsaved_changes": "Your changes haven't been saved.",
|
||||
"discard_changes": "Discard changes?",
|
||||
"discard": "Discard",
|
||||
"keep_editing": "Keep editing",
|
||||
"search_placeholder": "Search settings",
|
||||
|
||||
@@ -1118,7 +1118,7 @@
|
||||
"import_success": "Configuración importada exitosamente",
|
||||
"import_error": "Error al importar la configuración",
|
||||
"reset_confirm": "¿Está seguro de que desea restablecer toda la configuración a los valores predeterminados?",
|
||||
"unsaved_changes": "Tienes cambios sin guardar",
|
||||
"unsaved_changes": "Tus cambios no se han guardado.",
|
||||
"discard_changes": "¿Descartar los cambios?",
|
||||
"discard": "Descartar",
|
||||
"keep_editing": "Seguir editando",
|
||||
|
||||
@@ -1118,8 +1118,8 @@
|
||||
"import_success": "Seaded imporditud",
|
||||
"import_error": "Seadete importimine ebaõnnestus",
|
||||
"reset_confirm": "Kas soovid kindlasti lähtestada kõik seaded vaikeväärtustele?",
|
||||
"unsaved_changes": "Sul on salvestamata muudatusi",
|
||||
"discard_changes": "Kas loobuda salvestamata muudatustest?",
|
||||
"unsaved_changes": "Teie muudatusi pole salvestatud.",
|
||||
"discard_changes": "Kas loobuda muudatustest?",
|
||||
"discard": "Loobu",
|
||||
"keep_editing": "Jätka muutmist",
|
||||
"search_placeholder": "Otsi seadetest",
|
||||
|
||||
@@ -1118,8 +1118,8 @@
|
||||
"import_success": "تنظیمات با موفقیت وارد شد",
|
||||
"import_error": "وارد کردن تنظیمات ناموفق بود",
|
||||
"reset_confirm": "آیا از بازنشانی همه تنظیمات اطمینان دارید؟",
|
||||
"unsaved_changes": "تغییرات ذخیره نشده دارید",
|
||||
"discard_changes": "دور انداختن تغییرات ذخیره نشده؟",
|
||||
"unsaved_changes": "تغییرات شما ذخیره نشده است.",
|
||||
"discard_changes": "تغییرات دور انداخته شود؟",
|
||||
"discard": "دور انداختن",
|
||||
"keep_editing": "ادامه ویرایش",
|
||||
"search_placeholder": "جستجوی تنظیمات",
|
||||
@@ -3469,7 +3469,7 @@
|
||||
"add_phone": "افزودن تلفن",
|
||||
"save": "ذخیره",
|
||||
"cancel": "انصراف",
|
||||
"discard_title": "تغییرات دور انداخته شوند؟",
|
||||
"discard_title": "تغییرات دور انداخته شود؟",
|
||||
"discard_message": "تغییرات شما ذخیره نشده است.",
|
||||
"discard": "دور انداختن",
|
||||
"keep_editing": "ادامه ویرایش",
|
||||
|
||||
@@ -1118,7 +1118,7 @@
|
||||
"import_success": "Paramètres importés avec succès",
|
||||
"import_error": "Échec de l'importation des paramètres",
|
||||
"reset_confirm": "Êtes-vous sûr de vouloir réinitialiser tous les paramètres ?",
|
||||
"unsaved_changes": "Vous avez des modifications non enregistrées",
|
||||
"unsaved_changes": "Vos modifications n'ont pas été enregistrées.",
|
||||
"discard_changes": "Abandonner les modifications ?",
|
||||
"discard": "Abandonner",
|
||||
"keep_editing": "Continuer l'édition",
|
||||
|
||||
@@ -1083,10 +1083,10 @@
|
||||
"import_success": "ההגדרות יובאו בהצלחה",
|
||||
"import_error": "ייבוא ההגדרות נכשל",
|
||||
"reset_confirm": "האם אתה בטוח שברצונך לאפס את כל ההגדרות לברירות מחדל?",
|
||||
"unsaved_changes": "יש לך שינויים שלא נשמרו",
|
||||
"discard_changes": "למחוק שינויים שלא נשמרו?",
|
||||
"discard": "לזרוק",
|
||||
"keep_editing": "תמשיך לערוך",
|
||||
"unsaved_changes": "השינויים שלך לא נשמרו.",
|
||||
"discard_changes": "לבטל את השינויים?",
|
||||
"discard": "לבטל שינויים",
|
||||
"keep_editing": "להמשיך לערוך",
|
||||
"tabs": {
|
||||
"appearance": "מראה",
|
||||
"account": "חשבון",
|
||||
@@ -3373,8 +3373,8 @@
|
||||
"cancel": "לְבַטֵל",
|
||||
"discard_title": "לבטל את השינויים?",
|
||||
"discard_message": "השינויים שלך לא נשמרו.",
|
||||
"discard": "בטל",
|
||||
"keep_editing": "המשך לערוך",
|
||||
"discard": "לבטל שינויים",
|
||||
"keep_editing": "להמשיך לערוך",
|
||||
"remove_entry": "הסר",
|
||||
"close": "סגור",
|
||||
"remove_category": "הסר את {name}",
|
||||
|
||||
@@ -1118,8 +1118,8 @@
|
||||
"import_success": "Beállítások sikeresen importálva",
|
||||
"import_error": "Nem sikerült importálni a beállításokat",
|
||||
"reset_confirm": "Biztosan vissza akarod állítani az összes beállítást az alapértelmezettre?",
|
||||
"unsaved_changes": "Nem mentett változtatások vannak",
|
||||
"discard_changes": "Nem mentett változtatások elvetése?",
|
||||
"unsaved_changes": "A változtatásai nincsenek mentve.",
|
||||
"discard_changes": "Elveti a változtatásokat?",
|
||||
"discard": "Elvetés",
|
||||
"keep_editing": "Szerkesztés folytatása",
|
||||
"search_placeholder": "Beállítások keresése",
|
||||
|
||||
@@ -1118,9 +1118,9 @@
|
||||
"import_success": "Impostazioni importate con successo",
|
||||
"import_error": "Impossibile importare le impostazioni",
|
||||
"reset_confirm": "Sei sicuro di voler ripristinare tutte le impostazioni ai valori predefiniti?",
|
||||
"unsaved_changes": "Hai modifiche non salvate",
|
||||
"unsaved_changes": "Le modifiche non sono state salvate.",
|
||||
"discard_changes": "Annullare le modifiche?",
|
||||
"discard": "Annulla",
|
||||
"discard": "Annulla modifiche",
|
||||
"keep_editing": "Continua a modificare",
|
||||
"tabs": {
|
||||
"appearance": "Aspetto",
|
||||
@@ -3467,9 +3467,9 @@
|
||||
"add_phone": "Aggiungi telefono",
|
||||
"save": "Salva",
|
||||
"cancel": "Annulla",
|
||||
"discard_title": "Eliminare le modifiche?",
|
||||
"discard_title": "Annullare le modifiche?",
|
||||
"discard_message": "Le modifiche non sono state salvate.",
|
||||
"discard": "Elimina",
|
||||
"discard": "Annulla modifiche",
|
||||
"keep_editing": "Continua a modificare",
|
||||
"remove_entry": "Rimuovi",
|
||||
"close": "Chiudi",
|
||||
|
||||
@@ -1118,7 +1118,7 @@
|
||||
"import_success": "設定をインポートしました",
|
||||
"import_error": "設定のインポートに失敗しました",
|
||||
"reset_confirm": "すべての設定をデフォルトにリセットしてもよろしいですか?",
|
||||
"unsaved_changes": "保存されていない変更があります",
|
||||
"unsaved_changes": "変更はまだ保存されていません。",
|
||||
"discard_changes": "変更を破棄しますか?",
|
||||
"discard": "破棄",
|
||||
"keep_editing": "編集を続ける",
|
||||
@@ -3468,7 +3468,7 @@
|
||||
"save": "保存",
|
||||
"cancel": "キャンセル",
|
||||
"discard_title": "変更を破棄しますか?",
|
||||
"discard_message": "変更は保存されていません。",
|
||||
"discard_message": "変更はまだ保存されていません。",
|
||||
"discard": "破棄",
|
||||
"keep_editing": "編集を続ける",
|
||||
"remove_entry": "削除",
|
||||
|
||||
@@ -1118,9 +1118,9 @@
|
||||
"import_success": "설정을 성공적으로 가져왔어요",
|
||||
"import_error": "설정 가져오기에 실패했어요",
|
||||
"reset_confirm": "모든 설정을 기본값으로 되돌릴까요?",
|
||||
"unsaved_changes": "저장되지 않은 변경 사항이 있어요",
|
||||
"discard_changes": "변경 사항을 취소할까요?",
|
||||
"discard": "취소하기",
|
||||
"unsaved_changes": "변경 사항이 아직 저장되지 않았습니다.",
|
||||
"discard_changes": "변경 사항을 버릴까요?",
|
||||
"discard": "버리기",
|
||||
"keep_editing": "계속 수정하기",
|
||||
"tabs": {
|
||||
"appearance": "화면 설정",
|
||||
@@ -3467,10 +3467,10 @@
|
||||
"add_phone": "전화번호 추가",
|
||||
"save": "저장",
|
||||
"cancel": "취소",
|
||||
"discard_title": "변경 사항을 삭제할까요?",
|
||||
"discard_message": "변경 사항이 저장되지 않았습니다.",
|
||||
"discard": "삭제",
|
||||
"keep_editing": "계속 편집",
|
||||
"discard_title": "변경 사항을 버릴까요?",
|
||||
"discard_message": "변경 사항이 아직 저장되지 않았습니다.",
|
||||
"discard": "버리기",
|
||||
"keep_editing": "계속 수정하기",
|
||||
"remove_entry": "제거",
|
||||
"close": "닫기",
|
||||
"remove_category": "{name} 제거",
|
||||
|
||||
@@ -1118,8 +1118,8 @@
|
||||
"import_success": "Iestatījumi veiksmīgi importēti",
|
||||
"import_error": "Neizdevās importēt iestatījumus",
|
||||
"reset_confirm": "Vai tiešām vēlaties atiestatīt visus iestatījumus uz noklusējuma vērtībām?",
|
||||
"unsaved_changes": "Jums ir nesaglabātas izmaiņas",
|
||||
"discard_changes": "Atmest nesaglabātās izmaiņas?",
|
||||
"unsaved_changes": "Jūsu izmaiņas nav saglabātas.",
|
||||
"discard_changes": "Atmest izmaiņas?",
|
||||
"discard": "Atmest",
|
||||
"keep_editing": "Turpināt rediģēšanu",
|
||||
"tabs": {
|
||||
|
||||
@@ -1118,10 +1118,10 @@
|
||||
"import_success": "Тохиргоог амжилттай импортоллоо",
|
||||
"import_error": "Тохиргоог оруулж чадсангүй",
|
||||
"reset_confirm": "Та бүх тохиргоог өгөгдмөл рүү буцаахдаа итгэлтэй байна уу?",
|
||||
"unsaved_changes": "Танд хадгалагдаагүй өөрчлөлтүүд байна",
|
||||
"discard_changes": "Хадгалагдаагүй өөрчлөлтүүдийг устгах уу?",
|
||||
"discard": "Хасах",
|
||||
"keep_editing": "Засварлаж байгаарай",
|
||||
"unsaved_changes": "Таны өөрчлөлтүүд хадгалагдаагүй байна.",
|
||||
"discard_changes": "Өөрчлөлтүүдийг хаях уу?",
|
||||
"discard": "Хаях",
|
||||
"keep_editing": "Үргэлжлүүлэн засах",
|
||||
"search_placeholder": "Хайлтын тохиргоо",
|
||||
"search_clear": "Хайлтыг арилгах",
|
||||
"search_no_results": "Тохирох тохиргоо байхгүй",
|
||||
@@ -3469,8 +3469,8 @@
|
||||
"add_phone": "Утас нэмэх",
|
||||
"save": "Хадгалах",
|
||||
"cancel": "Цуцлах",
|
||||
"discard_title": "Өөрчлөлтийг хаях уу?",
|
||||
"discard_message": "Таны өөрчлөлт хадгалагдаагүй байна.",
|
||||
"discard_title": "Өөрчлөлтүүдийг хаях уу?",
|
||||
"discard_message": "Таны өөрчлөлтүүд хадгалагдаагүй байна.",
|
||||
"discard": "Хаях",
|
||||
"keep_editing": "Үргэлжлүүлэн засах",
|
||||
"remove_entry": "Хасах",
|
||||
|
||||
@@ -1118,8 +1118,8 @@
|
||||
"import_success": "Innstillingene er importert",
|
||||
"import_error": "Kunne ikke importere innstillinger",
|
||||
"reset_confirm": "Vil du tilbakestille alle innstillingene?",
|
||||
"unsaved_changes": "Du har ulagrede endringer",
|
||||
"discard_changes": "Vil du forkaste ulagrede endringer?",
|
||||
"unsaved_changes": "Endringene dine er ikke lagret.",
|
||||
"discard_changes": "Vil du forkaste endringene?",
|
||||
"discard": "Forkast",
|
||||
"keep_editing": "Fortsett å redigere",
|
||||
"search_placeholder": "Søk i innstillinger",
|
||||
|
||||
@@ -1118,7 +1118,7 @@
|
||||
"import_success": "Instellingen succesvol geïmporteerd",
|
||||
"import_error": "Kan instellingen niet importeren",
|
||||
"reset_confirm": "Weet je zeker dat je alle instellingen wilt resetten naar de standaardwaarden?",
|
||||
"unsaved_changes": "U heeft niet-opgeslagen wijzigingen",
|
||||
"unsaved_changes": "Je wijzigingen zijn niet opgeslagen.",
|
||||
"discard_changes": "Wijzigingen verwerpen?",
|
||||
"discard": "Verwerpen",
|
||||
"keep_editing": "Doorgaan met bewerken",
|
||||
|
||||
@@ -1118,8 +1118,8 @@
|
||||
"import_success": "Ustawienia zostały zaimportowane",
|
||||
"import_error": "Nie udało się zaimportować ustawień",
|
||||
"reset_confirm": "Czy na pewno chcesz przywrócić domyślne ustawienia?",
|
||||
"unsaved_changes": "Masz niezapisane zmiany",
|
||||
"discard_changes": "Odrzucić niezapisane zmiany?",
|
||||
"unsaved_changes": "Twoje zmiany nie zostały zapisane.",
|
||||
"discard_changes": "Odrzucić zmiany?",
|
||||
"discard": "Odrzuć",
|
||||
"keep_editing": "Kontynuuj edycję",
|
||||
"tabs": {
|
||||
|
||||
@@ -1118,7 +1118,7 @@
|
||||
"import_success": "Configurações importadas com sucesso",
|
||||
"import_error": "Falha ao importar configurações",
|
||||
"reset_confirm": "Tem certeza de que deseja redefinir todas as configurações para os padrões?",
|
||||
"unsaved_changes": "Você tem alterações não salvas",
|
||||
"unsaved_changes": "Suas alterações não foram salvas.",
|
||||
"discard_changes": "Descartar alterações?",
|
||||
"discard": "Descartar",
|
||||
"keep_editing": "Continuar editando",
|
||||
|
||||
@@ -1118,9 +1118,9 @@
|
||||
"import_success": "Setările au fost importate cu succes",
|
||||
"import_error": "Nu s-au putut importa setările",
|
||||
"reset_confirm": "Sunteți sigur că doriți să resetați toate setările la valorile implicite?",
|
||||
"unsaved_changes": "Aveți modificări nesalvate",
|
||||
"discard_changes": "Doriți să renunțați la modificările nesalvate?",
|
||||
"discard": "Ignorați",
|
||||
"unsaved_changes": "Modificările dvs. nu au fost salvate.",
|
||||
"discard_changes": "Renunțați la modificări?",
|
||||
"discard": "Renunțați",
|
||||
"keep_editing": "Continuați editarea",
|
||||
"search_placeholder": "Setări de căutare",
|
||||
"search_clear": "Șterge căutarea",
|
||||
|
||||
@@ -1118,9 +1118,9 @@
|
||||
"import_success": "Настройки успешно импортированы",
|
||||
"import_error": "Не удалось импортировать настройки",
|
||||
"reset_confirm": "Вы уверены, что хотите сбросить все настройки до значений по умолчанию?",
|
||||
"unsaved_changes": "У вас есть несохранённые изменения",
|
||||
"discard_changes": "Отменить несохранённые изменения?",
|
||||
"discard": "Отменить",
|
||||
"unsaved_changes": "Ваши изменения не сохранены.",
|
||||
"discard_changes": "Отменить изменения?",
|
||||
"discard": "Отменить изменения",
|
||||
"keep_editing": "Продолжить редактирование",
|
||||
"tabs": {
|
||||
"appearance": "Внешний вид",
|
||||
@@ -3469,7 +3469,7 @@
|
||||
"cancel": "Отмена",
|
||||
"discard_title": "Отменить изменения?",
|
||||
"discard_message": "Ваши изменения не сохранены.",
|
||||
"discard": "Отменить",
|
||||
"discard": "Отменить изменения",
|
||||
"keep_editing": "Продолжить редактирование",
|
||||
"remove_entry": "Убрать",
|
||||
"close": "Закрыть",
|
||||
|
||||
@@ -1118,9 +1118,9 @@
|
||||
"import_success": "Nastavenia boli úspešne importované",
|
||||
"import_error": "Import nastavení zlyhal",
|
||||
"reset_confirm": "Naozaj chcete obnoviť všetky nastavenia na predvolené?",
|
||||
"unsaved_changes": "Máte neuložené zmeny",
|
||||
"discard_changes": "Zahoditť neuložené zmeny?",
|
||||
"discard": "Zahoditť",
|
||||
"unsaved_changes": "Vaše zmeny neboli uložené.",
|
||||
"discard_changes": "Zahodiť zmeny?",
|
||||
"discard": "Zahodiť",
|
||||
"keep_editing": "Pokračovať v úprave",
|
||||
"search_placeholder": "Hľadať nastavenia",
|
||||
"search_clear": "Vymazať hľadanie",
|
||||
@@ -3472,7 +3472,7 @@
|
||||
"discard_title": "Zahodiť zmeny?",
|
||||
"discard_message": "Vaše zmeny neboli uložené.",
|
||||
"discard": "Zahodiť",
|
||||
"keep_editing": "Pokračovať v úpravách",
|
||||
"keep_editing": "Pokračovať v úprave",
|
||||
"remove_entry": "Odstrániť",
|
||||
"close": "Zavrieť",
|
||||
"remove_category": "Odstrániť {name}",
|
||||
|
||||
@@ -3297,8 +3297,8 @@
|
||||
"import_success": "นำเข้าการตั้งค่าเรียบร้อยแล้ว",
|
||||
"import_error": "นำเข้าการตั้งค่าไม่สำเร็จ",
|
||||
"reset_confirm": "คุณแน่ใจหรือไม่ว่าต้องการรีเซ็ตการตั้งค่าทั้งหมดกลับเป็นค่าเริ่มต้น?",
|
||||
"unsaved_changes": "คุณมีการเปลี่ยนแปลงที่ยังไม่ได้บันทึก",
|
||||
"discard_changes": "ละทิ้งการเปลี่ยนแปลงที่ยังไม่ได้บันทึกหรือไม่?",
|
||||
"unsaved_changes": "การเปลี่ยนแปลงของคุณยังไม่ได้บันทึก",
|
||||
"discard_changes": "ละทิ้งการเปลี่ยนแปลงหรือไม่?",
|
||||
"discard": "ละทิ้ง",
|
||||
"keep_editing": "แก้ไขต่อ",
|
||||
"search_placeholder": "ค้นหาการตั้งค่า",
|
||||
|
||||
@@ -1118,9 +1118,9 @@
|
||||
"import_success": "Ayarlar başarıyla içe aktarıldı",
|
||||
"import_error": "Ayarlar içe aktarılamadı",
|
||||
"reset_confirm": "Tüm ayarları varsayılanlara sıfırlamak istediğinizden emin misiniz?",
|
||||
"unsaved_changes": "Kaydedilmemiş değişiklikleriniz var",
|
||||
"discard_changes": "Kaydedilmemiş değişiklikler atılsın mı?",
|
||||
"discard": "Atla",
|
||||
"unsaved_changes": "Değişiklikleriniz kaydedilmedi.",
|
||||
"discard_changes": "Değişiklikler atılsın mı?",
|
||||
"discard": "Değişiklikleri at",
|
||||
"keep_editing": "Düzenlemeye devam et",
|
||||
"tabs": {
|
||||
"appearance": "Görünüm",
|
||||
@@ -3469,7 +3469,7 @@
|
||||
"cancel": "İptal",
|
||||
"discard_title": "Değişiklikler atılsın mı?",
|
||||
"discard_message": "Değişiklikleriniz kaydedilmedi.",
|
||||
"discard": "At",
|
||||
"discard": "Değişiklikleri at",
|
||||
"keep_editing": "Düzenlemeye devam et",
|
||||
"remove_entry": "Kaldır",
|
||||
"close": "Kapat",
|
||||
|
||||
@@ -1118,10 +1118,10 @@
|
||||
"import_success": "Налаштування успішно імпортовано",
|
||||
"import_error": "Не вдалося імпортувати налаштування",
|
||||
"reset_confirm": "Ви впевнені, що бажаєте скинути всі налаштування до стандартних?",
|
||||
"unsaved_changes": "У вас є незбережені зміни",
|
||||
"discard_changes": "Скасувати незбережені зміни?",
|
||||
"unsaved_changes": "Ваші зміни не збережено.",
|
||||
"discard_changes": "Відкинути зміни?",
|
||||
"discard": "Відкинути",
|
||||
"keep_editing": "Продовжуйте редагувати",
|
||||
"keep_editing": "Продовжити редагування",
|
||||
"tabs": {
|
||||
"appearance": "Зовнішній вигляд",
|
||||
"account": "Обліковий запис",
|
||||
|
||||
@@ -1118,8 +1118,8 @@
|
||||
"import_success": "已成功匯入設定",
|
||||
"import_error": "無法匯入設定",
|
||||
"reset_confirm": "您確定要將所有設定重設為預設值嗎?",
|
||||
"unsaved_changes": "您有尚未儲存的變更",
|
||||
"discard_changes": "要捨棄尚未儲存的變更嗎?",
|
||||
"unsaved_changes": "你的變更尚未儲存。",
|
||||
"discard_changes": "要捨棄變更嗎?",
|
||||
"discard": "捨棄",
|
||||
"keep_editing": "繼續編輯",
|
||||
"search_placeholder": "搜尋設定",
|
||||
@@ -3470,7 +3470,7 @@
|
||||
"save": "儲存",
|
||||
"cancel": "取消",
|
||||
"discard_title": "要捨棄變更嗎?",
|
||||
"discard_message": "您的變更尚未儲存。",
|
||||
"discard_message": "你的變更尚未儲存。",
|
||||
"discard": "捨棄",
|
||||
"keep_editing": "繼續編輯",
|
||||
"remove_entry": "移除",
|
||||
|
||||
@@ -1118,8 +1118,8 @@
|
||||
"import_success": "设置导入成功",
|
||||
"import_error": "导入设置失败",
|
||||
"reset_confirm": "您确定要将所有设置重置为默认值吗?",
|
||||
"unsaved_changes": "您有未保存的更改",
|
||||
"discard_changes": "放弃未保存的更改?",
|
||||
"unsaved_changes": "你的更改尚未保存。",
|
||||
"discard_changes": "放弃更改?",
|
||||
"discard": "放弃",
|
||||
"keep_editing": "继续编辑",
|
||||
"tabs": {
|
||||
@@ -3468,7 +3468,7 @@
|
||||
"save": "保存",
|
||||
"cancel": "取消",
|
||||
"discard_title": "放弃更改?",
|
||||
"discard_message": "您的更改尚未保存。",
|
||||
"discard_message": "你的更改尚未保存。",
|
||||
"discard": "放弃",
|
||||
"keep_editing": "继续编辑",
|
||||
"remove_entry": "移除",
|
||||
|
||||
Reference in New Issue
Block a user