feat(web): draw the export guide's countdown, title and description

The 10s countdown already existed as state - remainingMs, checkedAt and
paused were computed and consumed - but nothing rendered it, so the guide
showed no sign that it was about to dismiss itself.

The bar is one CSS width transition per run rather than a per-frame timer:
the remaining time is already known when the run starts, so animating to
zero over exactly that duration needs no re-render, and a pause just freezes
the transition.

Board copy added across all 19 locales.
This commit is contained in:
a1chzt
2026-09-22 23:42:23 +08:00
parent d27a36c7cd
commit d2c72f1624
23 changed files with 169 additions and 106 deletions
+2 -1
View File
@@ -17297,8 +17297,9 @@ function HtmlViewer({
<AfterExportShareGuide
key={afterExportGuide.noticeId}
labels={{
title: t('fileViewer.shareGuide.title'),
description: t('fileViewer.shareGuide.description'),
openShare: t('fileViewer.shareGuide.tryShare'),
close: t('common.close'),
neverShow: t('fileViewer.shareGuide.neverShowAgain'),
saveFailed: t('fileViewer.shareGuide.preferenceSaveFailed'),
}}
@@ -1,5 +1,6 @@
/* Adapted from Chain-6 .s-m1eexportprompt .prompt and .tool, not a replica
of the unavailable Owner-01 image. Keep the guide below the Share anchor. */
/* Restored from Board8 Chain-6-dialogs.dc.html, .s-m1eexportprompt scope, P1
"导出完成 · 分享引导条" mockup (width/pcheck/pfoot/minibar values below are
read directly off that markup). Keep the guide below the Share anchor. */
.guide {
position: absolute;
inset-block-start: calc(100% + 8px);
@@ -8,8 +9,7 @@
box-sizing: border-box;
display: flex;
flex-direction: column;
gap: 8px;
width: 240px;
width: 300px;
max-width: calc(100vw - 32px);
padding: 14px;
border: 1px solid #0000000D;
@@ -21,61 +21,79 @@
line-height: 18px;
}
.header {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
}
button.openShare {
display: flex;
align-items: center;
justify-content: flex-start;
gap: 6px;
min-width: 0;
height: auto;
padding: 0;
border: 0;
border-radius: 4px;
background: transparent;
color: #29292B;
margin: 0;
font-size: 13px;
font-weight: 600;
line-height: 20px;
text-align: start;
white-space: normal;
overflow-wrap: anywhere;
line-height: 18px;
}
.openShare svg { flex-shrink: 0; }
button.close {
display: flex;
flex: 0 0 20px;
.pcheck {
display: inline-flex;
flex: 0 0 16px;
align-items: center;
justify-content: center;
width: 20px;
min-width: 0;
height: 20px;
padding: 3px;
border: 0;
border-radius: 5px;
background: transparent;
color: #858585;
width: 16px;
height: 16px;
border-radius: 50%;
color: #4C9461;
background: #EEF6F0;
}
button.neverShow {
align-self: flex-start;
min-width: 0;
height: auto;
padding: 0;
border: 0;
border-radius: 4px;
background: transparent;
.desc {
margin: 4px 0 0;
color: #888888;
font-size: 12px;
font-weight: 400;
line-height: 18px;
white-space: normal;
text-align: start;
}
.openShare:hover, .neverShow:hover { text-decoration: underline; }
.close:hover { background: #F2F2F4; }
.pfoot {
display: flex;
justify-content: flex-end;
gap: 8px;
margin-top: 10px;
}
button.pghost {
box-sizing: border-box;
height: 28px;
padding: 0 12px;
border: 0;
border-radius: 5px;
background: #EDEDF0;
color: #333333;
font-size: 12px;
font-weight: 500;
white-space: nowrap;
}
button.paction {
box-sizing: border-box;
min-width: 76px;
height: 28px;
padding: 0 12px;
border: 0;
border-radius: 5px;
background: #282828;
color: #FFFFFF;
font-size: 12px;
font-weight: 500;
white-space: nowrap;
}
.pghost:hover { background: #E4E4E7; }
.paction:hover { background: #1F1F1F; }
.minibar {
position: relative;
width: 100%;
height: 3px;
margin-top: 10px;
border-radius: 2px;
background: #E2E2E5;
overflow: hidden;
}
.minibarFill {
position: absolute;
inset-block: 0;
inset-inline-start: 0;
width: 0%;
background: #282828;
}
.guide button:focus-visible { outline: 2px solid #29292B; outline-offset: 3px; }
.error { margin: 0; color: #C94E4E; font-size: 12px; line-height: 18px; }
.error { margin: 8px 0 0; color: #C94E4E; font-size: 12px; line-height: 18px; }
@@ -1,19 +1,22 @@
import { useEffect, useState } from 'react';
import { useEffect, useLayoutEffect, useRef, useState } from 'react';
import { Button } from '@open-design/components';
import { advanceShareGuideClock, startShareGuideClock } from './after-export-share-guide';
import { advanceShareGuideClock, startShareGuideClock, type ShareGuideClock } from './after-export-share-guide';
import styles from './AfterExportShareGuide.module.css';
const TOTAL_MS = 10_000;
/** Anchored guide borrowing the shared canvas prompt/tool visual language. */
export function AfterExportShareGuide({ onOpenShare, onDismiss, onNeverShow, labels }: {
onOpenShare: () => void;
onDismiss: () => void;
/** Return false when the permanent preference could not be persisted. */
onNeverShow: () => boolean;
labels: { openShare: string; close: string; neverShow: string; saveFailed: string };
labels: { title: string; description: string; openShare: string; neverShow: string; saveFailed: string };
}) {
const [clock, setClock] = useState(() => startShareGuideClock(performance.now()));
const [interaction, setInteraction] = useState({ hovered: false, focused: false });
const [saveFailed, setSaveFailed] = useState(false);
const fillRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (clock.paused) return;
const delay = Math.max(0, clock.remainingMs - (performance.now() - clock.checkedAt));
@@ -21,14 +24,31 @@ export function AfterExportShareGuide({ onOpenShare, onDismiss, onNeverShow, lab
return () => window.clearTimeout(timer);
}, [clock, onDismiss]);
// No per-frame timer: the countdown bar is a single CSS width transition per
// clock transition (mount, hover/focus change), not a rAF or interval loop.
useLayoutEffect(() => {
const fill = fillRef.current;
if (!fill) return;
const startPercent = (clock.remainingMs / TOTAL_MS) * 100;
fill.style.transition = 'none';
fill.style.width = `${startPercent}%`;
if (clock.paused) return;
// Force layout so the reverted (transition: none) width above is
// committed before re-enabling the transition below.
void fill.offsetWidth;
fill.style.transition = `width ${clock.remainingMs}ms linear`;
fill.style.width = '0%';
}, [clock]);
function updateInteraction(next: typeof interaction) {
setClock(previous => advanceShareGuideClock(previous, performance.now(), next));
setClock((previous: ShareGuideClock) => advanceShareGuideClock(previous, performance.now(), next));
setInteraction(next);
}
return (
<section
className={styles.guide}
aria-label={labels.openShare}
role="status"
aria-label={labels.title}
onMouseEnter={() => updateInteraction({ ...interaction, hovered: true })}
onMouseLeave={() => updateInteraction({ ...interaction, hovered: false })}
onFocusCapture={() => updateInteraction({ ...interaction, focused: true })}
@@ -36,21 +56,25 @@ export function AfterExportShareGuide({ onOpenShare, onDismiss, onNeverShow, lab
if (!event.currentTarget.contains(event.relatedTarget)) updateInteraction({ ...interaction, focused: false });
}}
>
<div className={styles.header}>
<Button className={styles.openShare} type="button" onClick={() => { onDismiss(); onOpenShare(); }}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" focusable="false">
<path d="M10 13.5a5 5 0 0 0 7 .2l3-3a5 5 0 0 0-7-7l-1.7 1.7M14 10.5a5 5 0 0 0-7-.2l-3 3a5 5 0 0 0 7 7l1.7-1.7" />
<strong className={styles.header}>
<span className={styles.pcheck} aria-hidden="true">
<svg width="13" height="13" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" focusable="false">
<path d="m3 8 3 3 7-7" />
</svg>
<span>{labels.openShare}</span>
</Button>
<Button className={styles.close} type="button" onClick={onDismiss} aria-label={labels.close}>
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" aria-hidden="true" focusable="false"><path d="m4 4 8 8M12 4l-8 8" /></svg>
</Button>
</span>
<span>{labels.title}</span>
</strong>
<p className={styles.desc}>{labels.description}</p>
<div className={styles.pfoot}>
<Button className={styles.pghost} type="button" onClick={() => {
if (onNeverShow()) onDismiss();
else setSaveFailed(true);
}}>{labels.neverShow}</Button>
<Button className={styles.paction} type="button" onClick={() => { onDismiss(); onOpenShare(); }}>{labels.openShare}</Button>
</div>
<div className={styles.minibar} aria-hidden="true">
<div ref={fillRef} className={styles.minibarFill} />
</div>
<Button className={styles.neverShow} type="button" onClick={() => {
if (onNeverShow()) onDismiss();
else setSaveFailed(true);
}}>{labels.neverShow}</Button>
{saveFailed ? <p className={styles.error} role="alert">{labels.saveFailed}</p> : null}
</section>
);
+3 -2
View File
@@ -237,9 +237,10 @@ export const ar: Dict = {
'fileViewer.commentSync.sessionMissing': "لم تسجّل الدخول. مزامنة التعليقات متوقفة مؤقتًا؛ تعليقات الزوار الجديدة غير ظاهرة حاليًا.",
'fileViewer.commentSync.shareStoppedPersonal': "الرابط معطّل. مزامنة التعليقات مع الصفحة المشتركة متوقفة مؤقتًا.",
'fileViewer.commentSync.shareStoppedTeam': "الرابط معطّل.",
'fileViewer.shareGuide.tryShare': "جرّب المشاركة",
'fileViewer.shareGuide.title': "اكتمل التصدير",
'fileViewer.shareGuide.description': "شارك الرابط وادعُ الآخرين لعرضه وترك التعليقات.",
'fileViewer.shareGuide.tryShare': "شارك الآن",
'fileViewer.shareGuide.neverShowAgain': "عدم الإظهار مجددًا",
'fileViewer.shareGuide.awaitingDesign': "بانتظار التصميم الأصلي",
'fileViewer.shareGuide.preferenceSaveFailed': "تعذّر حفظ التفضيل. حاول مجددًا.",
'common.close': 'إغلاق',
'common.clear': 'مسح',
+3 -2
View File
@@ -237,9 +237,10 @@ export const de: Dict = {
'fileViewer.commentSync.sessionMissing': "Nicht angemeldet. Die Kommentarsynchronisierung pausiert; neue Besucherkommentare sind vorübergehend nicht sichtbar.",
'fileViewer.commentSync.shareStoppedPersonal': "Der Link ist deaktiviert. Die Kommentarsynchronisierung mit der geteilten Seite pausiert.",
'fileViewer.commentSync.shareStoppedTeam': "Der Link ist deaktiviert.",
'fileViewer.shareGuide.tryShare': "Teilen ausprobieren",
'fileViewer.shareGuide.title': "Export abgeschlossen",
'fileViewer.shareGuide.description': "Teile den Link und lade andere ein, ihn anzusehen und zu kommentieren.",
'fileViewer.shareGuide.tryShare': "Jetzt teilen",
'fileViewer.shareGuide.neverShowAgain': "Nicht mehr anzeigen",
'fileViewer.shareGuide.awaitingDesign': "Designvorlage ausstehend",
'fileViewer.shareGuide.preferenceSaveFailed': "Einstellung konnte nicht gespeichert werden. Erneut versuchen.",
'common.close': 'Schließen',
'common.clear': 'Leeren',
+3 -2
View File
@@ -237,9 +237,10 @@ export const en: Dict = {
'fileViewer.commentSync.sessionMissing': "Signed out. Comment sync is paused; new visitor comments are temporarily unavailable.",
'fileViewer.commentSync.shareStoppedPersonal': "The link is disabled. Comment sync to the shared page is paused.",
'fileViewer.commentSync.shareStoppedTeam': "The link is disabled.",
'fileViewer.shareGuide.tryShare': "Try sharing",
'fileViewer.shareGuide.title': "Export complete",
'fileViewer.shareGuide.description': "Share the link and invite others to view it and leave comments.",
'fileViewer.shareGuide.tryShare': "Share",
'fileViewer.shareGuide.neverShowAgain': "Don't show again",
'fileViewer.shareGuide.awaitingDesign': "Awaiting design reference",
'fileViewer.shareGuide.preferenceSaveFailed': "Could not save preference. Try again.",
'common.close': 'Close',
'common.clear': 'Clear',
+3 -2
View File
@@ -237,9 +237,10 @@ export const esES: Dict = {
'fileViewer.commentSync.sessionMissing': "Sesión cerrada. La sincronización de comentarios está pausada; los nuevos comentarios de visitantes no están disponibles temporalmente.",
'fileViewer.commentSync.shareStoppedPersonal': "El enlace está desactivado. La sincronización de comentarios con la página compartida está en pausa.",
'fileViewer.commentSync.shareStoppedTeam': "El enlace está desactivado.",
'fileViewer.shareGuide.tryShare': "Probar compartir",
'fileViewer.shareGuide.title': "Exportación completada",
'fileViewer.shareGuide.description': "Comparte el enlace e invita a otros a verlo y dejar comentarios.",
'fileViewer.shareGuide.tryShare': "Compartir ahora",
'fileViewer.shareGuide.neverShowAgain': "No volver a mostrar",
'fileViewer.shareGuide.awaitingDesign': "Pendiente del diseño original",
'fileViewer.shareGuide.preferenceSaveFailed': "No se pudo guardar la preferencia. Inténtalo de nuevo.",
'common.close': 'Cerrar',
'common.clear': 'Limpiar',
+3 -2
View File
@@ -237,9 +237,10 @@ export const fa: Dict = {
'fileViewer.commentSync.sessionMissing': "وارد حساب نشده‌اید. همگام‌سازی نظرها موقتاً متوقف است؛ نظرهای جدید بازدیدکنندگان فعلاً نمایش داده نمی‌شوند.",
'fileViewer.commentSync.shareStoppedPersonal': "پیوند غیرفعال است. همگام‌سازی نظرها با صفحهٔ اشتراکی متوقف شده است.",
'fileViewer.commentSync.shareStoppedTeam': "پیوند غیرفعال است.",
'fileViewer.shareGuide.tryShare': "اشتراک‌گذاری را امتحان کنید",
'fileViewer.shareGuide.title': "خروجی گرفته شد",
'fileViewer.shareGuide.description': "پیوند را به اشتراک بگذارید و دیگران را برای مشاهده و ثبت نظر دعوت کنید.",
'fileViewer.shareGuide.tryShare': "اشتراک‌گذاری",
'fileViewer.shareGuide.neverShowAgain': "دیگر نمایش نده",
'fileViewer.shareGuide.awaitingDesign': "در انتظار طرح اصلی",
'fileViewer.shareGuide.preferenceSaveFailed': "ذخیرهٔ ترجیح ممکن نشد. دوباره تلاش کنید.",
'common.close': 'بستن',
'common.clear': 'پاک کردن',
+3 -2
View File
@@ -237,9 +237,10 @@ export const fr: Dict = {
'fileViewer.commentSync.sessionMissing': "Vous êtes déconnecté. La synchronisation des commentaires est suspendue ; les nouveaux commentaires des visiteurs sont temporairement invisibles.",
'fileViewer.commentSync.shareStoppedPersonal': "Le lien est désactivé. La synchronisation des commentaires avec la page partagée est suspendue.",
'fileViewer.commentSync.shareStoppedTeam': "Le lien est désactivé.",
'fileViewer.shareGuide.tryShare': "Essayer le partage",
'fileViewer.shareGuide.title': "Export terminé",
'fileViewer.shareGuide.description': "Partagez le lien et invitez les autres à le consulter et à laisser des commentaires.",
'fileViewer.shareGuide.tryShare': "Partager",
'fileViewer.shareGuide.neverShowAgain': "Ne plus afficher",
'fileViewer.shareGuide.awaitingDesign': "En attente du modèle",
'fileViewer.shareGuide.preferenceSaveFailed': "Impossible d’enregistrer la préférence. Réessayez.",
'common.close': 'Fermer',
'common.clear': 'Effacer',
+3 -2
View File
@@ -237,9 +237,10 @@ export const hu: Dict = {
'fileViewer.commentSync.sessionMissing': "Nincs bejelentkezve. A hozzászólások szinkronizálása szünetel; a látogatók új hozzászólásai átmenetileg nem láthatók.",
'fileViewer.commentSync.shareStoppedPersonal': "A hivatkozás le van tiltva. A hozzászólások szinkronizálása a megosztott oldallal szünetel.",
'fileViewer.commentSync.shareStoppedTeam': "A hivatkozás le van tiltva.",
'fileViewer.shareGuide.tryShare': "Megosztás kipróbálása",
'fileViewer.shareGuide.title': "Az exportálás befejeződött",
'fileViewer.shareGuide.description': "Oszd meg a linket, és hívj meg másokat megtekintésre és megjegyzések írására.",
'fileViewer.shareGuide.tryShare': "Megosztás",
'fileViewer.shareGuide.neverShowAgain': "Ne jelenjen meg újra",
'fileViewer.shareGuide.awaitingDesign': "Várakozás a látványtervre",
'fileViewer.shareGuide.preferenceSaveFailed': "A beállítás nem menthető. Próbálja újra.",
'common.close': 'Bezárás',
'common.clear': 'Törlés',
+3 -2
View File
@@ -237,9 +237,10 @@ export const id: Dict = {
'fileViewer.commentSync.sessionMissing': "Belum masuk. Sinkronisasi komentar dijeda; komentar baru pengunjung sementara tidak terlihat.",
'fileViewer.commentSync.shareStoppedPersonal': "Tautan dinonaktifkan. Sinkronisasi komentar ke halaman bersama dijeda.",
'fileViewer.commentSync.shareStoppedTeam': "Tautan dinonaktifkan.",
'fileViewer.shareGuide.tryShare': "Coba bagikan",
'fileViewer.shareGuide.title': "Ekspor selesai",
'fileViewer.shareGuide.description': "Bagikan tautan dan ajak orang lain untuk melihat serta memberikan komentar.",
'fileViewer.shareGuide.tryShare': "Bagikan sekarang",
'fileViewer.shareGuide.neverShowAgain': "Jangan tampilkan lagi",
'fileViewer.shareGuide.awaitingDesign': "Menunggu referensi desain",
'fileViewer.shareGuide.preferenceSaveFailed': "Gagal menyimpan preferensi. Coba lagi.",
'common.close': 'Tutup',
'common.clear': 'Bersihkan',
+3 -2
View File
@@ -237,9 +237,10 @@ export const it: Dict = {
'fileViewer.commentSync.sessionMissing': "Accesso non effettuato. La sincronizzazione dei commenti è sospesa; i nuovi commenti dei visitatori sono temporaneamente invisibili.",
'fileViewer.commentSync.shareStoppedPersonal': "Il link è disattivato. La sincronizzazione dei commenti con la pagina condivisa è sospesa.",
'fileViewer.commentSync.shareStoppedTeam': "Il link è disattivato.",
'fileViewer.shareGuide.tryShare': "Prova a condividere",
'fileViewer.shareGuide.title': "Esportazione completata",
'fileViewer.shareGuide.description': "Condividi il link e invita altri a visualizzarlo e lasciare commenti.",
'fileViewer.shareGuide.tryShare': "Condividi ora",
'fileViewer.shareGuide.neverShowAgain': "Non mostrare più",
'fileViewer.shareGuide.awaitingDesign': "In attesa del design originale",
'fileViewer.shareGuide.preferenceSaveFailed': "Impossibile salvare la preferenza. Riprova.",
'common.close': 'Chiudi',
'common.clear': 'Cancella',
+3 -2
View File
@@ -237,9 +237,10 @@ export const ja: Dict = {
'fileViewer.commentSync.sessionMissing': "ログインしていないためコメントの同期が一時停止しています。訪問者の新しいコメントは一時的に表示されません。",
'fileViewer.commentSync.shareStoppedPersonal': "リンクは無効です。共有ページへのコメント同期は一時停止しています。",
'fileViewer.commentSync.shareStoppedTeam': "リンクは無効です。",
'fileViewer.shareGuide.tryShare': "共有してみる",
'fileViewer.shareGuide.title': "エクスポート完了",
'fileViewer.shareGuide.description': "リンクを共有して、みんなに閲覧やコメントを依頼しましょう。",
'fileViewer.shareGuide.tryShare': "共有する",
'fileViewer.shareGuide.neverShowAgain': "今後表示しない",
'fileViewer.shareGuide.awaitingDesign': "デザイン資料待ち",
'fileViewer.shareGuide.preferenceSaveFailed': "設定を保存できませんでした。再試行してください。",
'common.close': '閉じる',
'common.clear': 'クリア',
+3 -2
View File
@@ -237,9 +237,10 @@ export const ko: Dict = {
'fileViewer.commentSync.sessionMissing': "로그아웃되어 댓글 동기화가 일시 중지되었습니다. 방문자의 새 댓글을 일시적으로 볼 수 없습니다.",
'fileViewer.commentSync.shareStoppedPersonal': "링크가 비활성화되었습니다. 공유 페이지로의 댓글 동기화가 일시 중지되었습니다.",
'fileViewer.commentSync.shareStoppedTeam': "링크가 비활성화되었습니다.",
'fileViewer.shareGuide.tryShare': "공유해 보기",
'fileViewer.shareGuide.title': "내보내기 완료",
'fileViewer.shareGuide.description': "링크를 공유하고 다른 사람에게 보기와 댓글 작성을 요청하세요.",
'fileViewer.shareGuide.tryShare': "공유하기",
'fileViewer.shareGuide.neverShowAgain': "다시 표시하지 않기",
'fileViewer.shareGuide.awaitingDesign': "디자인 원본 대기 중",
'fileViewer.shareGuide.preferenceSaveFailed': "설정을 저장하지 못했습니다. 다시 시도하세요.",
'common.close': '닫기',
'common.clear': '지우기',
+3 -2
View File
@@ -237,9 +237,10 @@ export const pl: Dict = {
'fileViewer.commentSync.sessionMissing': "Nie zalogowano. Synchronizacja komentarzy jest wstrzymana; nowe komentarze odwiedzających są tymczasowo niewidoczne.",
'fileViewer.commentSync.shareStoppedPersonal': "Link jest wyłączony. Synchronizacja komentarzy ze stroną udostępnioną jest wstrzymana.",
'fileViewer.commentSync.shareStoppedTeam': "Link jest wyłączony.",
'fileViewer.shareGuide.tryShare': "Wypróbuj udostępnianie",
'fileViewer.shareGuide.title': "Eksport zakończony",
'fileViewer.shareGuide.description': "Udostępnij link i zaproś innych do przeglądania i zostawiania komentarzy.",
'fileViewer.shareGuide.tryShare': "Udostępnij",
'fileViewer.shareGuide.neverShowAgain': "Nie pokazuj ponownie",
'fileViewer.shareGuide.awaitingDesign': "Oczekiwanie na projekt",
'fileViewer.shareGuide.preferenceSaveFailed': "Nie udało się zapisać ustawienia. Spróbuj ponownie.",
'common.close': 'Zamknij',
'common.clear': 'Wyczyść',
+3 -2
View File
@@ -237,9 +237,10 @@ export const ptBR: Dict = {
'fileViewer.commentSync.sessionMissing': "Sessão encerrada. A sincronização de comentários está pausada; novos comentários de visitantes estão temporariamente indisponíveis.",
'fileViewer.commentSync.shareStoppedPersonal': "O link está desativado. A sincronização de comentários com a página compartilhada está pausada.",
'fileViewer.commentSync.shareStoppedTeam': "O link está desativado.",
'fileViewer.shareGuide.tryShare': "Experimente compartilhar",
'fileViewer.shareGuide.title': "Exportação concluída",
'fileViewer.shareGuide.description': "Compartilhe o link e convide outras pessoas para visualizar e deixar comentários.",
'fileViewer.shareGuide.tryShare': "Compartilhar agora",
'fileViewer.shareGuide.neverShowAgain': "Não mostrar novamente",
'fileViewer.shareGuide.awaitingDesign': "Aguardando referência visual",
'fileViewer.shareGuide.preferenceSaveFailed': "Não foi possível salvar a preferência. Tente novamente.",
'common.close': 'Fechar',
'common.clear': 'Limpar',
+3 -2
View File
@@ -237,9 +237,10 @@ export const ru: Dict = {
'fileViewer.commentSync.sessionMissing': "Вы не вошли в аккаунт. Синхронизация комментариев приостановлена; новые комментарии посетителей временно не видны.",
'fileViewer.commentSync.shareStoppedPersonal': "Ссылка отключена. Синхронизация комментариев со страницей общего доступа приостановлена.",
'fileViewer.commentSync.shareStoppedTeam': "Ссылка отключена.",
'fileViewer.shareGuide.tryShare': "Попробовать поделиться",
'fileViewer.shareGuide.title': "Экспорт завершён",
'fileViewer.shareGuide.description': "Поделитесь ссылкой и пригласите других посмотреть и оставить комментарии.",
'fileViewer.shareGuide.tryShare': "Поделиться",
'fileViewer.shareGuide.neverShowAgain': "Больше не показывать",
'fileViewer.shareGuide.awaitingDesign': "Ожидание исходного дизайна",
'fileViewer.shareGuide.preferenceSaveFailed': "Не удалось сохранить настройку. Повторите попытку.",
'common.close': 'Закрыть',
'common.clear': 'Очистить',
+3 -2
View File
@@ -237,9 +237,10 @@ export const th: Dict = {
'fileViewer.commentSync.sessionMissing': "ยังไม่ได้เข้าสู่ระบบ การซิงค์ความคิดเห็นหยุดชั่วคราว จึงยังไม่เห็นความคิดเห็นใหม่ของผู้เข้าชม",
'fileViewer.commentSync.shareStoppedPersonal': "ลิงก์ถูกปิดใช้งาน การซิงค์ความคิดเห็นไปยังหน้าที่แชร์หยุดชั่วคราว",
'fileViewer.commentSync.shareStoppedTeam': "ลิงก์ถูกปิดใช้งาน",
'fileViewer.shareGuide.tryShare': "ลองแชร์",
'fileViewer.shareGuide.title': "ส่งออกเสร็จสมบูรณ์",
'fileViewer.shareGuide.description': "แชร์ลิงก์และเชิญผู้อื่นมาดูและแสดงความคิดเห็น",
'fileViewer.shareGuide.tryShare': "แชร์เลย",
'fileViewer.shareGuide.neverShowAgain': "ไม่ต้องแสดงอีก",
'fileViewer.shareGuide.awaitingDesign': "รอภาพต้นแบบ",
'fileViewer.shareGuide.preferenceSaveFailed': "บันทึกการตั้งค่าไม่ได้ โปรดลองอีกครั้ง",
'common.close': 'ปิด',
'common.clear': 'ล้าง',
+3 -2
View File
@@ -237,9 +237,10 @@ export const tr: Dict = {
'fileViewer.commentSync.sessionMissing': "Oturum kapalı. Yorum eşitlemesi duraklatıldı; ziyaretçilerin yeni yorumları geçici olarak görünmüyor.",
'fileViewer.commentSync.shareStoppedPersonal': "Bağlantı devre dışı. Paylaşılan sayfaya yorum eşitlemesi duraklatıldı.",
'fileViewer.commentSync.shareStoppedTeam': "Bağlantı devre dışı.",
'fileViewer.shareGuide.tryShare': "Paylaşmayı deneyin",
'fileViewer.shareGuide.title': "Dışa aktarma tamamlandı",
'fileViewer.shareGuide.description': "Bağlantıyı paylaşın ve başkalarını görüntülemeye ve yorum bırakmaya davet edin.",
'fileViewer.shareGuide.tryShare': "Paylaş",
'fileViewer.shareGuide.neverShowAgain': "Bir daha gösterme",
'fileViewer.shareGuide.awaitingDesign': "Tasarım referansı bekleniyor",
'fileViewer.shareGuide.preferenceSaveFailed': "Tercih kaydedilemedi. Yeniden deneyin.",
'common.close': 'Kapat',
'common.clear': 'Temizle',
+3 -2
View File
@@ -237,9 +237,10 @@ export const uk: Dict = {
'fileViewer.commentSync.sessionMissing': "Ви не ввійшли в обліковий запис. Синхронізацію коментарів призупинено; нові коментарі відвідувачів тимчасово не видно.",
'fileViewer.commentSync.shareStoppedPersonal': "Посилання вимкнено. Синхронізацію коментарів зі спільною сторінкою призупинено.",
'fileViewer.commentSync.shareStoppedTeam': "Посилання вимкнено.",
'fileViewer.shareGuide.tryShare': "Спробувати поділитися",
'fileViewer.shareGuide.title': "Експорт завершено",
'fileViewer.shareGuide.description': "Поділіться посиланням і запросіть інших переглянути та залишити коментарі.",
'fileViewer.shareGuide.tryShare': "Поділитися",
'fileViewer.shareGuide.neverShowAgain': "Більше не показувати",
'fileViewer.shareGuide.awaitingDesign': "Очікування оригінального дизайну",
'fileViewer.shareGuide.preferenceSaveFailed': "Не вдалося зберегти налаштування. Спробуйте ще раз.",
'common.close': 'Закрити',
'common.clear': 'Очистити',
+3 -2
View File
@@ -245,9 +245,10 @@ export const zhCN: Dict = {
'fileViewer.commentSync.sessionMissing': "未登录,评论暂停同步,访客的新评论暂时看不到。",
'fileViewer.commentSync.shareStoppedPersonal': "链接已停用,评论暂停同步到分享页。",
'fileViewer.commentSync.shareStoppedTeam': "链接已停用。",
'fileViewer.shareGuide.tryShare': "试试分享",
'fileViewer.shareGuide.title': "导出完成",
'fileViewer.shareGuide.description': "分享链接,邀请大家查看并留下评论。",
'fileViewer.shareGuide.tryShare': "去分享",
'fileViewer.shareGuide.neverShowAgain': "不再提示",
'fileViewer.shareGuide.awaitingDesign': "待原图",
'fileViewer.shareGuide.preferenceSaveFailed': "偏好保存失败,请重试。",
"common.close": "关闭",
"common.clear": "清除",
+3 -2
View File
@@ -245,9 +245,10 @@ export const zhTW: Dict = {
'fileViewer.commentSync.sessionMissing': "尚未登入,評論暫停同步,暫時看不到訪客的新評論。",
'fileViewer.commentSync.shareStoppedPersonal': "連結已停用,評論暫停同步到分享頁。",
'fileViewer.commentSync.shareStoppedTeam': "連結已停用。",
'fileViewer.shareGuide.tryShare': "試試分享",
'fileViewer.shareGuide.title': "匯出完成",
'fileViewer.shareGuide.description': "分享連結,邀請大家查看並留下留言。",
'fileViewer.shareGuide.tryShare': "去分享",
'fileViewer.shareGuide.neverShowAgain': "不再提示",
'fileViewer.shareGuide.awaitingDesign': "待原圖",
'fileViewer.shareGuide.preferenceSaveFailed': "偏好儲存失敗,請重試。",
"common.close": "關閉",
"common.clear": "清除",
+2 -1
View File
@@ -137,9 +137,10 @@ export interface Dict {
'fileViewer.commentSync.sessionMissing': string;
'fileViewer.commentSync.shareStoppedPersonal': string;
'fileViewer.commentSync.shareStoppedTeam': string;
'fileViewer.shareGuide.title': string;
'fileViewer.shareGuide.description': string;
'fileViewer.shareGuide.tryShare': string;
'fileViewer.shareGuide.neverShowAgain': string;
'fileViewer.shareGuide.awaitingDesign': string;
'fileViewer.shareGuide.preferenceSaveFailed': string;
'common.close': string;
'common.clear': string;