pgkiln 0.88.0 → 0.90.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -408,7 +408,6 @@ export const it: BuilderMessages = {
408
408
  'pd.not_found': 'Componente non trovato.',
409
409
  'pd.save_page': 'Salva pagina',
410
410
  'pd.delete_page': 'Elimina pagina',
411
- 'pd.delete_page_confirm': 'Eliminare la pagina {n} e tutti i suoi componenti?',
412
411
  'pd.filter_label': 'Filtra proprietà',
413
412
  'pd.filter': 'Filtro',
414
413
  'pd.help_hint': 'Selezionare una proprietà per visualizzarne qui la guida.',
@@ -1427,7 +1426,6 @@ export const it: BuilderMessages = {
1427
1426
  'st.ts_format': 'Formato data e ora',
1428
1427
  'st.ts_format_ph': 'ad es. DD-MM-YYYY HH24:MI',
1429
1428
  'st.save_settings': 'Salva impostazioni',
1430
- 'st.delete_confirm': 'Eliminare l’applicazione {app} e tutte le sue pagine?',
1431
1429
  'st.delete': 'Elimina applicazione',
1432
1430
  'st.error_fn': 'Funzione di gestione degli errori',
1433
1431
  'st.error_fn_ph': 'ad es. sales.error_message',
@@ -1474,8 +1472,8 @@ export const it: BuilderMessages = {
1474
1472
  'us.signin': 'Accesso',
1475
1473
  'us.status': 'Stato',
1476
1474
  'us.none': 'nessuna',
1477
- 'us.password': 'password',
1478
- 'us.no_password': 'nessuna password',
1475
+ 'us.password': 'Password',
1476
+ 'us.no_password': 'Nessuna password',
1479
1477
  'us.active': 'attivo',
1480
1478
  'us.inactive': 'non attivo',
1481
1479
  'us.last': 'ultimo {at}',
@@ -1845,8 +1843,8 @@ export const it: BuilderMessages = {
1845
1843
  'mfa.locked_out': 'Smarriti telefono, chiave e codici? Chiedere a un amministratore di reimpostare l’accesso a due fattori.',
1846
1844
  'mfa.wrong': 'Il codice non è corretto oppure è già stato usato.',
1847
1845
  'mfa.column': 'Due fattori',
1848
- 'mfa.on': 'attivo',
1849
- 'mfa.off': 'non attivo',
1846
+ 'mfa.on': 'Attivo',
1847
+ 'mfa.off': 'Non attivo',
1850
1848
  'mfa.reset': 'Reimposta',
1851
1849
  'mfa.reason': 'Motivo',
1852
1850
  'mfa.reset_help': 'Rimuove le app e i codici di recupero di {user} e lo disconnette. Viene registrato; gli amministratori vengono avvisati via e-mail.',
@@ -7516,4 +7514,41 @@ export const it: BuilderMessages = {
7516
7514
  'pwa.prefetch_hours': 'Recuperarle di nuovo dopo (ore)',
7517
7515
  'pwa.prefetch_hours_help': 'Da 1 a 168. Le pagine vengono recuperate di nuovo alla prima pagina aperta dopo questo tempo, se c’è connessione.',
7518
7516
  'pwa.prefetch_hours_range': 'Recuperarle di nuovo dopo: un numero intero di ore da 1 a 168.',
7517
+ // ------------------------------------------------------------ SQL Worksheet: one toolbar row (UX-1)
7518
+ 'ws.more': 'Altre azioni',
7519
+ 'ws.suggest': 'Suggerisci',
7520
+ 'ws.suggest_title': 'Suggerimenti al cursore (Ctrl+Spazio)',
7521
+ 'ws.check': 'Verifica',
7522
+ 'ws.check_title': 'Pianifica l’SQL senza eseguirlo, come l’Advisor',
7523
+ 'ws.key.indent': 'Rientra (Esc, poi Tab: campo successivo)',
7524
+ 'ws.search_path_plain': '{schema} per primo nel percorso di ricerca',
7525
+ // ------------------------------------------------------------ Rail labels (UX-3)
7526
+ 'rail.labels_show': 'Mostra etichette',
7527
+ 'rail.labels_hide': 'Nascondi etichette',
7528
+ // ------------------------------------------------------------ Administration page (UX-4)
7529
+ 'wu.filter': 'Filtra le utilità',
7530
+ 'wu.filter_none': 'Nessun risultato per il filtro.',
7531
+ 'wu.sec.people': 'Persone e accesso',
7532
+ 'wu.sec.connections': 'Connessioni',
7533
+ 'wu.sec.data': 'Dati e IA',
7534
+ 'wu.sec.operations': 'Operazioni',
7535
+ 'wu.sec.workspace': 'Area di lavoro {name}',
7536
+ 'wu.sec.instance': 'Istanza',
7537
+ // ------------------------------------------------------------ Workspace home: needs attention (UX-13)
7538
+ 'wh.attention': 'Richiede attenzione',
7539
+ // ------------------------------------------------------------ Delete with a typed confirmation (UX-6)
7540
+ 'st.danger_zone': 'Zona pericolosa',
7541
+ 'st.delete_text': 'L’eliminazione di {app} rimuove pagine, componenti condivisi, copie di lavoro e anche i backup; non si può annullare. Esportala prima se potrebbe servirti ancora.',
7542
+ 'st.delete_type': 'Digita l’alias {alias} per confermare',
7543
+ 'st.delete_mismatch': 'Digita l’alias dell’applicazione, {alias}, per eliminarla.',
7544
+ 'pd.delete_type': 'Digita il numero di pagina {n} per confermare',
7545
+ 'pd.delete_mismatch': 'Digita il numero di pagina, {n}, per eliminare la pagina.',
7546
+ // ------------------------------------------------------------ Create application: name first, a sticky footer (UX-7)
7547
+ 'aw.data_and_pages': 'Dati e pagine',
7548
+ 'aw.sign_in': 'Accesso',
7549
+ 'aw.sum_on': '{n} pagine su {schema}',
7550
+ 'aw.sum_on_1': '{n} pagina su {schema}',
7551
+ 'aw.sum_new': 'Una nuova applicazione con il proprio schema',
7552
+ // ------------------------------------------------------------ A side drawer's Close (UX-8)
7553
+ 'common.close': 'Chiudi',
7519
7554
  };
@@ -408,7 +408,6 @@ export const ja: BuilderMessages = {
408
408
  'pd.not_found': 'コンポーネントが見つかりません。',
409
409
  'pd.save_page': 'ページの保存',
410
410
  'pd.delete_page': 'ページの削除',
411
- 'pd.delete_page_confirm': 'ページ {n} とそのすべてのコンポーネントを削除しますか。',
412
411
  'pd.filter_label': 'プロパティのフィルタ',
413
412
  'pd.filter': 'フィルタ',
414
413
  'pd.help_hint': 'プロパティを選択すると、ここにヘルプが表示されます。',
@@ -1427,7 +1426,6 @@ export const ja: BuilderMessages = {
1427
1426
  'st.ts_format': '日時書式',
1428
1427
  'st.ts_format_ph': '例: DD-MM-YYYY HH24:MI',
1429
1428
  'st.save_settings': '設定の保存',
1430
- 'st.delete_confirm': 'アプリケーション {app} とそのすべてのページを削除しますか。',
1431
1429
  'st.delete': 'アプリケーションの削除',
1432
1430
  'st.error_fn': 'エラー処理関数',
1433
1431
  'st.error_fn_ph': '例: sales.error_message',
@@ -7516,4 +7514,41 @@ export const ja: BuilderMessages = {
7516
7514
  'pwa.prefetch_hours': '再取得までの時間(時間)',
7517
7515
  'pwa.prefetch_hours_help': '1~168。この時間が過ぎた後、接続があるときに最初にページを開くと再取得されます。',
7518
7516
  'pwa.prefetch_hours_range': '再取得までの時間: 1~168 の整数の時間を指定してください。',
7517
+ // ------------------------------------------------------------ SQL Worksheet: one toolbar row (UX-1)
7518
+ 'ws.more': 'その他の操作',
7519
+ 'ws.suggest': '候補',
7520
+ 'ws.suggest_title': 'カーソル位置の候補 (Ctrl+Space)',
7521
+ 'ws.check': 'チェック',
7522
+ 'ws.check_title': 'Advisor と同様に、実行せずに SQL を計画します',
7523
+ 'ws.key.indent': 'インデント(Esc の後 Tab: 次のフィールド)',
7524
+ 'ws.search_path_plain': '検索パスの先頭は {schema}',
7525
+ // ------------------------------------------------------------ Rail labels (UX-3)
7526
+ 'rail.labels_show': 'ラベルを表示',
7527
+ 'rail.labels_hide': 'ラベルを非表示',
7528
+ // ------------------------------------------------------------ Administration page (UX-4)
7529
+ 'wu.filter': 'ユーティリティを絞り込む',
7530
+ 'wu.filter_none': 'フィルターに一致するものはありません。',
7531
+ 'wu.sec.people': 'ユーザーとサインイン',
7532
+ 'wu.sec.connections': '接続',
7533
+ 'wu.sec.data': 'データと AI',
7534
+ 'wu.sec.operations': '運用',
7535
+ 'wu.sec.workspace': 'ワークスペース {name}',
7536
+ 'wu.sec.instance': 'インスタンス',
7537
+ // ------------------------------------------------------------ Workspace home: needs attention (UX-13)
7538
+ 'wh.attention': '要対応',
7539
+ // ------------------------------------------------------------ Delete with a typed confirmation (UX-6)
7540
+ 'st.danger_zone': '危険な操作',
7541
+ 'st.delete_text': '{app} を削除すると、ページ、共有コンポーネント、作業コピー、バックアップも削除され、元に戻せません。再び必要になる可能性がある場合は、先にエクスポートしてください。',
7542
+ 'st.delete_type': '確認のため別名 {alias} を入力してください',
7543
+ 'st.delete_mismatch': '削除するには、アプリケーションの別名 {alias} を入力してください。',
7544
+ 'pd.delete_type': '確認のためページ番号 {n} を入力してください',
7545
+ 'pd.delete_mismatch': 'ページを削除するには、ページ番号 {n} を入力してください。',
7546
+ // ------------------------------------------------------------ Create application: name first, a sticky footer (UX-7)
7547
+ 'aw.data_and_pages': 'データとページ',
7548
+ 'aw.sign_in': 'サインイン',
7549
+ 'aw.sum_on': '{schema} の {n} ページ',
7550
+ 'aw.sum_on_1': '{schema} の {n} ページ',
7551
+ 'aw.sum_new': '独自のスキーマを持つ新しいアプリケーション',
7552
+ // ------------------------------------------------------------ A side drawer's Close (UX-8)
7553
+ 'common.close': '閉じる',
7519
7554
  };
@@ -408,7 +408,6 @@ export const ko: BuilderMessages = {
408
408
  'pd.not_found': '구성요소를 찾을 수 없습니다.',
409
409
  'pd.save_page': '페이지 저장',
410
410
  'pd.delete_page': '페이지 삭제',
411
- 'pd.delete_page_confirm': '페이지 {n}과(와) 모든 구성요소를 삭제하시겠습니까?',
412
411
  'pd.filter_label': '속성 필터',
413
412
  'pd.filter': '필터',
414
413
  'pd.help_hint': '속성을 선택하면 여기에 도움말이 표시됩니다.',
@@ -1427,7 +1426,6 @@ export const ko: BuilderMessages = {
1427
1426
  'st.ts_format': '날짜 및 시간 형식',
1428
1427
  'st.ts_format_ph': '예: DD-MM-YYYY HH24:MI',
1429
1428
  'st.save_settings': '설정 저장',
1430
- 'st.delete_confirm': '애플리케이션 {app}과(와) 모든 페이지를 삭제하시겠습니까?',
1431
1429
  'st.delete': '애플리케이션 삭제',
1432
1430
  'st.error_fn': '오류 처리 함수',
1433
1431
  'st.error_fn_ph': '예: sales.error_message',
@@ -7516,4 +7514,41 @@ export const ko: BuilderMessages = {
7516
7514
  'pwa.prefetch_hours': '다시 가져오기까지의 시간(시간)',
7517
7515
  'pwa.prefetch_hours_help': '1~168. 이 시간이 지난 뒤 연결되어 있을 때 처음 페이지를 열면 다시 가져옵니다.',
7518
7516
  'pwa.prefetch_hours_range': '다시 가져오기까지의 시간: 1~168 사이의 정수 시간입니다.',
7517
+ // ------------------------------------------------------------ SQL Worksheet: one toolbar row (UX-1)
7518
+ 'ws.more': '추가 작업',
7519
+ 'ws.suggest': '제안',
7520
+ 'ws.suggest_title': '커서 위치의 제안 (Ctrl+Space)',
7521
+ 'ws.check': '검사',
7522
+ 'ws.check_title': 'Advisor처럼 실행하지 않고 SQL을 계획합니다',
7523
+ 'ws.key.indent': '들여쓰기 (Esc 후 Tab: 다음 필드)',
7524
+ 'ws.search_path_plain': '검색 경로의 첫 번째는 {schema}',
7525
+ // ------------------------------------------------------------ Rail labels (UX-3)
7526
+ 'rail.labels_show': '레이블 표시',
7527
+ 'rail.labels_hide': '레이블 숨기기',
7528
+ // ------------------------------------------------------------ Administration page (UX-4)
7529
+ 'wu.filter': '유틸리티 필터',
7530
+ 'wu.filter_none': '필터와 일치하는 항목이 없습니다.',
7531
+ 'wu.sec.people': '사용자 및 로그인',
7532
+ 'wu.sec.connections': '연결',
7533
+ 'wu.sec.data': '데이터 및 AI',
7534
+ 'wu.sec.operations': '운영',
7535
+ 'wu.sec.workspace': '작업 공간 {name}',
7536
+ 'wu.sec.instance': '인스턴스',
7537
+ // ------------------------------------------------------------ Workspace home: needs attention (UX-13)
7538
+ 'wh.attention': '주의 필요',
7539
+ // ------------------------------------------------------------ Delete with a typed confirmation (UX-6)
7540
+ 'st.danger_zone': '위험 구역',
7541
+ 'st.delete_text': '{app}을(를) 삭제하면 페이지, 공유 구성 요소, 작업 사본과 백업도 함께 삭제되며 되돌릴 수 없습니다. 다시 필요할 수 있다면 먼저 내보내십시오.',
7542
+ 'st.delete_type': '확인하려면 별칭 {alias}을(를) 입력하십시오',
7543
+ 'st.delete_mismatch': '삭제하려면 애플리케이션의 별칭 {alias}을(를) 입력하십시오.',
7544
+ 'pd.delete_type': '확인하려면 페이지 번호 {n}을(를) 입력하십시오',
7545
+ 'pd.delete_mismatch': '페이지를 삭제하려면 페이지 번호 {n}을(를) 입력하십시오.',
7546
+ // ------------------------------------------------------------ Create application: name first, a sticky footer (UX-7)
7547
+ 'aw.data_and_pages': '데이터와 페이지',
7548
+ 'aw.sign_in': '로그인',
7549
+ 'aw.sum_on': '{schema}의 페이지 {n}개',
7550
+ 'aw.sum_on_1': '{schema}의 페이지 {n}개',
7551
+ 'aw.sum_new': '자체 스키마를 가진 새 애플리케이션',
7552
+ // ------------------------------------------------------------ A side drawer's Close (UX-8)
7553
+ 'common.close': '닫기',
7519
7554
  };
@@ -408,7 +408,6 @@ export const nl: BuilderMessages = {
408
408
  'pd.not_found': 'Component niet gevonden.',
409
409
  'pd.save_page': 'Pagina opslaan',
410
410
  'pd.delete_page': 'Pagina verwijderen',
411
- 'pd.delete_page_confirm': 'Pagina {n} en al haar componenten verwijderen?',
412
411
  'pd.filter_label': 'Eigenschappen filteren',
413
412
  'pd.filter': 'Filteren',
414
413
  'pd.help_hint': 'Selecteer een eigenschap om hier de help ervan te zien.',
@@ -1427,7 +1426,6 @@ export const nl: BuilderMessages = {
1427
1426
  'st.ts_format': 'Notatie van datum en tijd',
1428
1427
  'st.ts_format_ph': 'bijv. DD-MM-YYYY HH24:MI',
1429
1428
  'st.save_settings': 'Instellingen opslaan',
1430
- 'st.delete_confirm': 'Applicatie {app} met al haar pagina’s verwijderen?',
1431
1429
  'st.delete': 'Applicatie verwijderen',
1432
1430
  'st.error_fn': 'Functie voor foutafhandeling',
1433
1431
  'st.error_fn_ph': 'bijv. sales.error_message',
@@ -1474,8 +1472,8 @@ export const nl: BuilderMessages = {
1474
1472
  'us.signin': 'Aanmelden',
1475
1473
  'us.status': 'Status',
1476
1474
  'us.none': 'geen',
1477
- 'us.password': 'wachtwoord',
1478
- 'us.no_password': 'geen wachtwoord',
1475
+ 'us.password': 'Wachtwoord',
1476
+ 'us.no_password': 'Geen wachtwoord',
1479
1477
  'us.active': 'actief',
1480
1478
  'us.inactive': 'inactief',
1481
1479
  'us.last': 'laatst {at}',
@@ -1845,8 +1843,8 @@ export const nl: BuilderMessages = {
1845
1843
  'mfa.locked_out': 'Telefoon, sleutel en codes kwijt? Vraag een beheerder uw aanmelden in twee stappen te resetten.',
1846
1844
  'mfa.wrong': 'Die code klopt niet of is al gebruikt.',
1847
1845
  'mfa.column': 'Twee stappen',
1848
- 'mfa.on': 'aan',
1849
- 'mfa.off': 'uit',
1846
+ 'mfa.on': 'Aan',
1847
+ 'mfa.off': 'Uit',
1850
1848
  'mfa.reset': 'Resetten',
1851
1849
  'mfa.reason': 'Reden',
1852
1850
  'mfa.reset_help': 'Verwijdert de apps en herstelcodes van {user} en meldt deze af. Wordt gelogd; de beheerders krijgen een e-mail.',
@@ -7516,4 +7514,41 @@ export const nl: BuilderMessages = {
7516
7514
  'pwa.prefetch_hours': 'Opnieuw ophalen na (uren)',
7517
7515
  'pwa.prefetch_hours_help': '1 tot 168. De pagina\'s worden opnieuw opgehaald bij de eerste pagina die na deze tijd wordt geopend, als er verbinding is.',
7518
7516
  'pwa.prefetch_hours_range': 'Opnieuw ophalen na: een geheel aantal uren van 1 tot 168.',
7517
+ // ------------------------------------------------------------ SQL Worksheet: one toolbar row (UX-1)
7518
+ 'ws.more': 'Meer acties',
7519
+ 'ws.suggest': 'Suggesties',
7520
+ 'ws.suggest_title': 'Suggesties bij de cursor (Ctrl+Spatie)',
7521
+ 'ws.check': 'Controleren',
7522
+ 'ws.check_title': 'De SQL plannen zonder hem uit te voeren, zoals de Advisor',
7523
+ 'ws.key.indent': 'Inspringen (Esc, dan Tab: volgend veld)',
7524
+ 'ws.search_path_plain': '{schema} eerst in het zoekpad',
7525
+ // ------------------------------------------------------------ Rail labels (UX-3)
7526
+ 'rail.labels_show': 'Labels tonen',
7527
+ 'rail.labels_hide': 'Labels verbergen',
7528
+ // ------------------------------------------------------------ Administration page (UX-4)
7529
+ 'wu.filter': 'Hulpmiddelen filteren',
7530
+ 'wu.filter_none': 'Niets voldoet aan het filter.',
7531
+ 'wu.sec.people': 'Mensen en aanmelden',
7532
+ 'wu.sec.connections': 'Verbindingen',
7533
+ 'wu.sec.data': 'Gegevens en AI',
7534
+ 'wu.sec.operations': 'Beheer',
7535
+ 'wu.sec.workspace': 'Werkruimte {name}',
7536
+ 'wu.sec.instance': 'Instantie',
7537
+ // ------------------------------------------------------------ Workspace home: needs attention (UX-13)
7538
+ 'wh.attention': 'Vraagt aandacht',
7539
+ // ------------------------------------------------------------ Delete with a typed confirmation (UX-6)
7540
+ 'st.danger_zone': 'Gevarenzone',
7541
+ 'st.delete_text': 'Verwijderen van {app} verwijdert de pagina\'s, gedeelde componenten, werkkopieën en ook de back-ups; dat kan niet ongedaan worden gemaakt. Exporteer de applicatie eerst als u haar nog nodig kunt hebben.',
7542
+ 'st.delete_type': 'Typ de alias {alias} ter bevestiging',
7543
+ 'st.delete_mismatch': 'Typ de alias van de applicatie, {alias}, om haar te verwijderen.',
7544
+ 'pd.delete_type': 'Typ het paginanummer {n} ter bevestiging',
7545
+ 'pd.delete_mismatch': 'Typ het paginanummer, {n}, om de pagina te verwijderen.',
7546
+ // ------------------------------------------------------------ Create application: name first, a sticky footer (UX-7)
7547
+ 'aw.data_and_pages': 'Gegevens en pagina\'s',
7548
+ 'aw.sign_in': 'Aanmelden',
7549
+ 'aw.sum_on': '{n} pagina\'s op {schema}',
7550
+ 'aw.sum_on_1': '{n} pagina op {schema}',
7551
+ 'aw.sum_new': 'Een nieuwe applicatie met een eigen schema',
7552
+ // ------------------------------------------------------------ A side drawer's Close (UX-8)
7553
+ 'common.close': 'Sluiten',
7519
7554
  };
@@ -408,7 +408,6 @@ export const pt: BuilderMessages = {
408
408
  'pd.not_found': 'Componente não encontrado.',
409
409
  'pd.save_page': 'Salvar página',
410
410
  'pd.delete_page': 'Excluir página',
411
- 'pd.delete_page_confirm': 'Excluir a página {n} e todos os seus componentes?',
412
411
  'pd.filter_label': 'Filtrar propriedades',
413
412
  'pd.filter': 'Filtrar',
414
413
  'pd.help_hint': 'Selecione uma propriedade para ver a ajuda dela aqui.',
@@ -1427,7 +1426,6 @@ export const pt: BuilderMessages = {
1427
1426
  'st.ts_format': 'Formato de data e hora',
1428
1427
  'st.ts_format_ph': 'por exemplo DD-MM-YYYY HH24:MI',
1429
1428
  'st.save_settings': 'Salvar configurações',
1430
- 'st.delete_confirm': 'Excluir a aplicação {app} e todas as suas páginas?',
1431
1429
  'st.delete': 'Excluir aplicação',
1432
1430
  'st.error_fn': 'Função de tratamento de erros',
1433
1431
  'st.error_fn_ph': 'por exemplo sales.error_message',
@@ -1474,8 +1472,8 @@ export const pt: BuilderMessages = {
1474
1472
  'us.signin': 'Login',
1475
1473
  'us.status': 'Status',
1476
1474
  'us.none': 'nenhuma',
1477
- 'us.password': 'senha',
1478
- 'us.no_password': 'sem senha',
1475
+ 'us.password': 'Senha',
1476
+ 'us.no_password': 'Sem senha',
1479
1477
  'us.active': 'ativa',
1480
1478
  'us.inactive': 'inativa',
1481
1479
  'us.last': 'último {at}',
@@ -1845,8 +1843,8 @@ export const pt: BuilderMessages = {
1845
1843
  'mfa.locked_out': 'Perdeu o telefone, a chave e os códigos? Peça a um administrador para redefinir seu login em duas etapas.',
1846
1844
  'mfa.wrong': 'Esse código não está certo ou já foi usado.',
1847
1845
  'mfa.column': 'Duas etapas',
1848
- 'mfa.on': 'ativado',
1849
- 'mfa.off': 'desativado',
1846
+ 'mfa.on': 'Ativado',
1847
+ 'mfa.off': 'Desativado',
1850
1848
  'mfa.reset': 'Redefinir',
1851
1849
  'mfa.reason': 'Motivo',
1852
1850
  'mfa.reset_help': 'Remove os aplicativos e códigos de recuperação de {user} e encerra a sessão. Fica registrado; os administradores recebem um e-mail.',
@@ -7516,4 +7514,41 @@ export const pt: BuilderMessages = {
7516
7514
  'pwa.prefetch_hours': 'Buscá-las novamente após (horas)',
7517
7515
  'pwa.prefetch_hours_help': 'De 1 a 168. As páginas são buscadas novamente na primeira página aberta após esse tempo, quando houver conexão.',
7518
7516
  'pwa.prefetch_hours_range': 'Buscá-las novamente após: um número inteiro de horas de 1 a 168.',
7517
+ // ------------------------------------------------------------ SQL Worksheet: one toolbar row (UX-1)
7518
+ 'ws.more': 'Mais ações',
7519
+ 'ws.suggest': 'Sugerir',
7520
+ 'ws.suggest_title': 'Sugestões no cursor (Ctrl+Espaço)',
7521
+ 'ws.check': 'Verificar',
7522
+ 'ws.check_title': 'Planejar o SQL sem executá-lo, como o Advisor',
7523
+ 'ws.key.indent': 'Recuar (Esc e depois Tab: próximo campo)',
7524
+ 'ws.search_path_plain': '{schema} primeiro no caminho de pesquisa',
7525
+ // ------------------------------------------------------------ Rail labels (UX-3)
7526
+ 'rail.labels_show': 'Mostrar rótulos',
7527
+ 'rail.labels_hide': 'Ocultar rótulos',
7528
+ // ------------------------------------------------------------ Administration page (UX-4)
7529
+ 'wu.filter': 'Filtrar os utilitários',
7530
+ 'wu.filter_none': 'Nada corresponde ao filtro.',
7531
+ 'wu.sec.people': 'Pessoas e login',
7532
+ 'wu.sec.connections': 'Conexões',
7533
+ 'wu.sec.data': 'Dados e IA',
7534
+ 'wu.sec.operations': 'Operações',
7535
+ 'wu.sec.workspace': 'Espaço de trabalho {name}',
7536
+ 'wu.sec.instance': 'Instância',
7537
+ // ------------------------------------------------------------ Workspace home: needs attention (UX-13)
7538
+ 'wh.attention': 'Requer atenção',
7539
+ // ------------------------------------------------------------ Delete with a typed confirmation (UX-6)
7540
+ 'st.danger_zone': 'Zona de perigo',
7541
+ 'st.delete_text': 'Excluir {app} remove suas páginas, componentes compartilhados, cópias de trabalho e também seus backups; não pode ser desfeito. Exporte-a antes se puder precisar dela novamente.',
7542
+ 'st.delete_type': 'Digite o alias {alias} para confirmar',
7543
+ 'st.delete_mismatch': 'Digite o alias do aplicativo, {alias}, para excluí-lo.',
7544
+ 'pd.delete_type': 'Digite o número da página {n} para confirmar',
7545
+ 'pd.delete_mismatch': 'Digite o número da página, {n}, para excluir a página.',
7546
+ // ------------------------------------------------------------ Create application: name first, a sticky footer (UX-7)
7547
+ 'aw.data_and_pages': 'Dados e páginas',
7548
+ 'aw.sign_in': 'Início de sessão',
7549
+ 'aw.sum_on': '{n} páginas sobre {schema}',
7550
+ 'aw.sum_on_1': '{n} página sobre {schema}',
7551
+ 'aw.sum_new': 'Uma nova aplicação com o seu próprio esquema',
7552
+ // ------------------------------------------------------------ A side drawer's Close (UX-8)
7553
+ 'common.close': 'Fechar',
7519
7554
  };
@@ -408,7 +408,6 @@ export const zhCN: BuilderMessages = {
408
408
  'pd.not_found': '未找到组件。',
409
409
  'pd.save_page': '保存页面',
410
410
  'pd.delete_page': '删除页面',
411
- 'pd.delete_page_confirm': '删除页面 {n} 及其所有组件?',
412
411
  'pd.filter_label': '筛选属性',
413
412
  'pd.filter': '筛选',
414
413
  'pd.help_hint': '选择一个属性以在此处查看其帮助。',
@@ -1427,7 +1426,6 @@ export const zhCN: BuilderMessages = {
1427
1426
  'st.ts_format': '日期和时间格式',
1428
1427
  'st.ts_format_ph': '例如 DD-MM-YYYY HH24:MI',
1429
1428
  'st.save_settings': '保存设置',
1430
- 'st.delete_confirm': '删除应用程序 {app} 及其所有页面?',
1431
1429
  'st.delete': '删除应用程序',
1432
1430
  'st.error_fn': '错误处理函数',
1433
1431
  'st.error_fn_ph': '例如 sales.error_message',
@@ -7516,4 +7514,41 @@ export const zhCN: BuilderMessages = {
7516
7514
  'pwa.prefetch_hours': '多少小时后重新获取',
7517
7515
  'pwa.prefetch_hours_help': '1 到 168。超过此时间后,在有网络连接时打开第一个页面时会重新获取这些页面。',
7518
7516
  'pwa.prefetch_hours_range': '重新获取时间:1 到 168 之间的整数小时。',
7517
+ // ------------------------------------------------------------ SQL Worksheet: one toolbar row (UX-1)
7518
+ 'ws.more': '更多操作',
7519
+ 'ws.suggest': '建议',
7520
+ 'ws.suggest_title': '光标处的建议 (Ctrl+Space)',
7521
+ 'ws.check': '检查',
7522
+ 'ws.check_title': '像 Advisor 一样规划 SQL 而不运行',
7523
+ 'ws.key.indent': '缩进(先按 Esc 再按 Tab:下一个字段)',
7524
+ 'ws.search_path_plain': '{schema} 位于搜索路径首位',
7525
+ // ------------------------------------------------------------ Rail labels (UX-3)
7526
+ 'rail.labels_show': '显示标签',
7527
+ 'rail.labels_hide': '隐藏标签',
7528
+ // ------------------------------------------------------------ Administration page (UX-4)
7529
+ 'wu.filter': '筛选实用工具',
7530
+ 'wu.filter_none': '没有符合筛选条件的项目。',
7531
+ 'wu.sec.people': '人员与登录',
7532
+ 'wu.sec.connections': '连接',
7533
+ 'wu.sec.data': '数据与 AI',
7534
+ 'wu.sec.operations': '运维',
7535
+ 'wu.sec.workspace': '工作区 {name}',
7536
+ 'wu.sec.instance': '实例',
7537
+ // ------------------------------------------------------------ Workspace home: needs attention (UX-13)
7538
+ 'wh.attention': '需要注意',
7539
+ // ------------------------------------------------------------ Delete with a typed confirmation (UX-6)
7540
+ 'st.danger_zone': '危险区域',
7541
+ 'st.delete_text': '删除 {app} 会移除其页面、共享组件、工作副本以及备份;此操作无法撤销。如果以后可能还需要,请先导出。',
7542
+ 'st.delete_type': '输入别名 {alias} 以确认',
7543
+ 'st.delete_mismatch': '输入应用程序的别名 {alias} 才能删除它。',
7544
+ 'pd.delete_type': '输入页码 {n} 以确认',
7545
+ 'pd.delete_mismatch': '输入页码 {n} 才能删除该页面。',
7546
+ // ------------------------------------------------------------ Create application: name first, a sticky footer (UX-7)
7547
+ 'aw.data_and_pages': '数据和页面',
7548
+ 'aw.sign_in': '登录',
7549
+ 'aw.sum_on': '{schema} 上的 {n} 个页面',
7550
+ 'aw.sum_on_1': '{schema} 上的 {n} 个页面',
7551
+ 'aw.sum_new': '一个拥有自己模式的新应用程序',
7552
+ // ------------------------------------------------------------ A side drawer's Close (UX-8)
7553
+ 'common.close': '关闭',
7519
7554
  };
@@ -408,7 +408,6 @@ export const zhTW: BuilderMessages = {
408
408
  'pd.not_found': '找不到元件。',
409
409
  'pd.save_page': '儲存頁面',
410
410
  'pd.delete_page': '刪除頁面',
411
- 'pd.delete_page_confirm': '要刪除頁面 {n} 及其所有元件嗎?',
412
411
  'pd.filter_label': '篩選屬性',
413
412
  'pd.filter': '篩選',
414
413
  'pd.help_hint': '選取屬性即可在此查看其說明。',
@@ -1427,7 +1426,6 @@ export const zhTW: BuilderMessages = {
1427
1426
  'st.ts_format': '日期與時間格式',
1428
1427
  'st.ts_format_ph': '例如 DD-MM-YYYY HH24:MI',
1429
1428
  'st.save_settings': '儲存設定',
1430
- 'st.delete_confirm': '要刪除應用程式 {app} 及其所有頁面嗎?',
1431
1429
  'st.delete': '刪除應用程式',
1432
1430
  'st.error_fn': '錯誤處理函數',
1433
1431
  'st.error_fn_ph': '例如 sales.error_message',
@@ -7516,4 +7514,41 @@ export const zhTW: BuilderMessages = {
7516
7514
  'pwa.prefetch_hours': '多少小時後重新取得',
7517
7515
  'pwa.prefetch_hours_help': '1 到 168。超過此時間後,在有網路連線時開啟第一個頁面時會重新取得這些頁面。',
7518
7516
  'pwa.prefetch_hours_range': '重新取得時間:1 到 168 之間的整數小時。',
7517
+ // ------------------------------------------------------------ SQL Worksheet: one toolbar row (UX-1)
7518
+ 'ws.more': '更多動作',
7519
+ 'ws.suggest': '建議',
7520
+ 'ws.suggest_title': '游標處的建議 (Ctrl+Space)',
7521
+ 'ws.check': '檢查',
7522
+ 'ws.check_title': '像 Advisor 一樣規劃 SQL 而不執行',
7523
+ 'ws.key.indent': '縮排(先按 Esc 再按 Tab:下一個欄位)',
7524
+ 'ws.search_path_plain': '{schema} 位於搜尋路徑首位',
7525
+ // ------------------------------------------------------------ Rail labels (UX-3)
7526
+ 'rail.labels_show': '顯示標籤',
7527
+ 'rail.labels_hide': '隱藏標籤',
7528
+ // ------------------------------------------------------------ Administration page (UX-4)
7529
+ 'wu.filter': '篩選公用程式',
7530
+ 'wu.filter_none': '沒有符合篩選條件的項目。',
7531
+ 'wu.sec.people': '人員與登入',
7532
+ 'wu.sec.connections': '連線',
7533
+ 'wu.sec.data': '資料與 AI',
7534
+ 'wu.sec.operations': '維運',
7535
+ 'wu.sec.workspace': '工作區 {name}',
7536
+ 'wu.sec.instance': '執行個體',
7537
+ // ------------------------------------------------------------ Workspace home: needs attention (UX-13)
7538
+ 'wh.attention': '需要注意',
7539
+ // ------------------------------------------------------------ Delete with a typed confirmation (UX-6)
7540
+ 'st.danger_zone': '危險區域',
7541
+ 'st.delete_text': '刪除 {app} 會移除其頁面、共用元件、工作副本以及備份;此動作無法復原。如果日後可能還需要,請先匯出。',
7542
+ 'st.delete_type': '輸入別名 {alias} 以確認',
7543
+ 'st.delete_mismatch': '輸入應用程式的別名 {alias} 才能刪除它。',
7544
+ 'pd.delete_type': '輸入頁碼 {n} 以確認',
7545
+ 'pd.delete_mismatch': '輸入頁碼 {n} 才能刪除該頁面。',
7546
+ // ------------------------------------------------------------ Create application: name first, a sticky footer (UX-7)
7547
+ 'aw.data_and_pages': '資料和頁面',
7548
+ 'aw.sign_in': '登入',
7549
+ 'aw.sum_on': '{schema} 上的 {n} 個頁面',
7550
+ 'aw.sum_on_1': '{schema} 上的 {n} 個頁面',
7551
+ 'aw.sum_new': '一個擁有自己結構描述的新應用程式',
7552
+ // ------------------------------------------------------------ A side drawer's Close (UX-8)
7553
+ 'common.close': '關閉',
7519
7554
  };
@@ -540,6 +540,24 @@ export async function builderRoutes(app: FastifyInstance) {
540
540
  return reply.redirect(`${BASE}/login`, 303);
541
541
  });
542
542
 
543
+ // (UX-3) the icon rail with labels next to the icons, or icons only (kept in the developer's session)
544
+ app.post(`${BASE}/rail`, async (req: Req, reply) => {
545
+ const s = await developer(req, reply);
546
+ if (!s) return;
547
+ if (req.body?.labels === 'labels') s.state.__RAIL = 'labels';
548
+ else delete s.state.__RAIL;
549
+ const ref = String(req.headers.referer ?? '');
550
+ let to = `${BASE}/home`;
551
+ try {
552
+ const u = new URL(ref);
553
+ if (u.host === req.headers.host && u.pathname.startsWith(BASE)) to = u.pathname + u.search;
554
+ } catch {
555
+ /* no referer: the home page */
556
+ }
557
+ await saveState(s);
558
+ return reply.redirect(to, 303);
559
+ });
560
+
543
561
  // The builder's light/dark theme (the developer's menu in the icon rail).
544
562
  app.post(`${BASE}/theme`, async (req: Req, reply) => {
545
563
  const s = await developer(req, reply);
@@ -640,6 +658,8 @@ export async function builderRoutes(app: FastifyInstance) {
640
658
  // (089) page groups: a column and a filter (?group=name, or "-" for pages without one)
641
659
  const groups = (await owner.query<{ name: string }>('select name from meta.page_group where app_id = $1 order by name', [a.id])).rows.map((g) => g.name);
642
660
  const grouped = groups.length > 0 || pages.rows.some((p) => p.page_group);
661
+ // (UX-9) the property editor's words for a page's mode
662
+ const modeLabel = (m: string) => (m === 'modal' ? tx('pdz.modal_dialog') : tx('pdz.normal'));
643
663
  const groupFilter = typeof req.query?.group === 'string' ? req.query.group : '';
644
664
  // (sprint 74) search by name or number, and a report or icon view (APEX: the application home)
645
665
  const q = typeof req.query?.q === 'string' ? req.query.q.trim().slice(0, 100) : '';
@@ -654,7 +674,7 @@ export async function builderRoutes(app: FastifyInstance) {
654
674
  const tx = tr(s);
655
675
 
656
676
  const main = html`
657
- ${appHeader(a, 'pages', s)}
677
+ ${appHeader(a, 'pages', s, [`${BASE}/apps/${a.id}/create-page`, tx('app.create_page'), 'plus'])}
658
678
  ${appLock && appLock.locked_by !== s.username ? html`<div class="alert alert-error" role="status">${icon('key')} ${lockText(appLock)} ${tx('app.lock_refused')}</div>` : ''}
659
679
  <div class="app-home">
660
680
  <div class="app-home-main">
@@ -664,18 +684,17 @@ export async function builderRoutes(app: FastifyInstance) {
664
684
  <button class="btn">${icon('search')}<span class="sr-only">${tx('common.search')}</span></button></form>
665
685
  <div class="seg view-toggle" role="group" aria-label="${tx('ab.view')}">
666
686
  <a href="${keep({})}"${icons ? '' : raw(' aria-current="true"')}>${icon('list')} ${tx('ab.view_report')}</a><a href="${keep({ view: 'icons' })}"${icons ? raw(' aria-current="true"') : ''}>${icon('grid')} ${tx('app.view_icons')}</a></div>
667
- <a class="btn btn-hot" href="${BASE}/apps/${a.id}/create-page">${icon('plus')} ${tx('app.create_page')}</a>
668
687
  </div>
669
688
  ${region(tx('app.tab.pages'), html`${grouped
670
689
  ? html`<form method="get" class="search u-mwnone u-mb1"><div class="field"><label class="label" for="f_group">${tx('app.page_group')}</label>
671
690
  <select id="f_group" name="group">${[['', tx('app.all_pages')], ...groups.map((g) => [g, g]), ['-', tx('app.no_group')]].map(([v, l]) => html`<option value="${v}"${v === groupFilter ? raw(' selected') : ''}>${l}</option>`)}</select></div>
672
691
  <button class="btn u-selfend">${tx('common.show')}</button></form>`
673
692
  : ''}${icons
674
- ? html`<ul class="page-icons" id="pages-rows">${shownPages.map((p) => html`<li><a href="${designerUrl(a.id, p.page_no)}" class="page-icon"><span class="page-icon-no">${p.page_no}</span><b>${p.name}</b><small class="muted">${p.mode}, ${tx(p.regions === 1 ? 'app.regions_one' : 'app.regions', { n: p.regions })}</small></a></li>`)}</ul>`
693
+ ? html`<ul class="page-icons" id="pages-rows">${shownPages.map((p) => html`<li><a href="${designerUrl(a.id, p.page_no)}" class="page-icon"><span class="page-icon-no">${p.page_no}</span><b>${p.name}</b><small class="muted">${modeLabel(p.mode)}, ${tx(p.regions === 1 ? 'app.regions_one' : 'app.regions', { n: p.regions })}</small></a></li>`)}</ul>`
675
694
  : html`<div class="table-wrap"><table class="report">
676
695
  <thead><tr><th class="num">${tx('app.col.page')}</th><th>${tx('ab.col.name')}</th>${grouped ? html`<th>${tx('app.col.group')}</th>` : ''}<th>${tx('app.col.mode')}</th><th class="num">${tx('app.col.regions')}</th><th class="num">${tx('app.col.items')}</th><th class="num">${tx('app.col.das')}</th><th class="num">${tx('app.col.processes')}</th><th>${tx('app.col.authz')}</th><th>${tx('app.col.protection')}</th><th>${tx('app.col.lock')}</th><th></th></tr></thead>
677
696
  <tbody id="pages-rows">${shownPages.map((p) => html`<tr>
678
- <td class="num">${p.page_no}</td><td><a href="${designerUrl(a.id, p.page_no)}">${p.name}</a>${commentsPerPage.get(p.page_no) ? html` <span class="tag" title="${tx('app.dev_comments')}">${tx(commentsPerPage.get(p.page_no) === 1 ? 'app.comments_one' : 'app.comments', { n: commentsPerPage.get(p.page_no) })}</span>` : ''}${issues.tag(p.page_no)}</td>${grouped ? html`<td>${p.page_group ?? '—'}</td>` : ''}<td>${p.mode}</td>
697
+ <td class="num">${p.page_no}</td><td><a href="${designerUrl(a.id, p.page_no)}">${p.name}</a>${commentsPerPage.get(p.page_no) ? html` <span class="tag" title="${tx('app.dev_comments')}">${tx(commentsPerPage.get(p.page_no) === 1 ? 'app.comments_one' : 'app.comments', { n: commentsPerPage.get(p.page_no) })}</span>` : ''}${issues.tag(p.page_no)}</td>${grouped ? html`<td>${p.page_group ?? ''}</td>` : ''}<td>${modeLabel(p.mode)}</td>
679
698
  <td class="num">${p.regions}</td><td class="num">${p.items}</td><td class="num">${p.das}</td><td class="num">${p.processes}</td>
680
699
  <td>${p.requires_auth ? (p.authz ?? '—') : tx('app.public')}</td><td>${p.protection}</td>
681
700
  <td>${((l) => (l ? html`<span class="lock-tag" title="${lockText(l)}">${icon('key')}<span>${l.locked_by === s.username ? tx('app.you') : l.locked_by}</span></span>` : '—'))(locks.get(p.page_no))}</td>
@@ -690,7 +709,7 @@ export async function builderRoutes(app: FastifyInstance) {
690
709
  ${select('kind', tx('app.page_type'), 'report_form', WIZARD_KINDS.map(([k, label]): [string, string] => [k, kindLabel(k, label)]))}
691
710
  ${select('table', tx('app.table_or_view'), '', tables.map((t): [string, string] => [t.t, t.access ? t.t : tx('app.no_access', { table: t.t, role: a.db_role })]))}
692
711
  </div>
693
- <div class="buttons"><button class="btn btn-hot">${tx('common.next')}</button></div>
712
+ <div class="buttons"><button class="btn">${tx('common.next')}</button></div>
694
713
  </form>
695
714
  <p><a href="${BASE}/apps/${a.id}/create-page">${tx('app.all_page_types')} ▸</a></p>
696
715
  <p><a href="${BASE}/apps/${a.id}/ai-pages">${tx('app.ai_pages')} ▸</a> <span class="muted">${tx('app.ai_pages_note')}</span></p>`)}
@@ -699,28 +718,22 @@ export async function builderRoutes(app: FastifyInstance) {
699
718
  <div class="form-grid">
700
719
  ${input('page_no', tx('app.page_number'), nextPage, { type: 'number', required: true })}
701
720
  ${input('name', tx('ab.col.name'), '', { required: true })}
702
- ${select('mode', tx('app.col.mode'), 'normal', ['normal', 'modal'])}
721
+ ${select('mode', tx('app.col.mode'), 'normal', [['normal', tx('pdz.normal')], ['modal', tx('pdz.modal_dialog')]])}
703
722
  ${input('parent_page', tx('app.parent'), a.home_page, { type: 'number' })}
704
723
  </div>
705
- <div class="buttons"><button class="btn btn-hot">${tx('app.create_page')}</button></div>
724
+ <div class="buttons"><button class="btn">${tx('app.create_page')}</button></div>
706
725
  </form>`)}
707
726
  </div>
708
727
  </div>
709
728
  <aside class="app-tasks region region-standard" aria-labelledby="app-tasks-h"><header class="region-header"><h2 id="app-tasks-h">${tx('common.tasks')}</h2></header>
710
729
  <ul class="sc-links">
711
- <li><a href="/a/${a.alias}" target="_blank" rel="noopener">${icon('play')} ${tx('app.task.run')}</a></li>
712
- <li><a href="${BASE}/apps/${a.id}/create-page">${icon('plus')} ${tx('app.create_page')}</a></li>
713
730
  <li><a href="${BASE}/apps/${a.id}/create-page?tab=feature">${icon('puzzle')} ${tx('app.task.add_feature')}</a></li>
714
731
  <li><a href="${BASE}/apps/${a.id}/create-page?tab=copy">${icon('copy')} ${tx('app.task.copy_page')}</a></li>
715
732
  <li><a href="${BASE}/apps/${a.id}/ai-pages">${icon('lightbulb')} ${tx('app.ai_pages')}</a></li>
716
- <li><a href="${BASE}/apps/${a.id}/shared">${icon('layers')} ${tx('app.tab.shared')}</a></li>
717
733
  <li><a href="${BASE}/apps/${a.id}/shared?type=page_group">${icon('folder')} ${tx('app.task.page_groups')}</a></li>
718
- <li><a href="${BASE}/apps/${a.id}/export">${icon('download')} ${tx('app.head.export')}</a></li>
719
- <li><a href="${BASE}/apps/${a.id}/backups">${icon('history')} ${tx('app.head.backups')}</a></li>
720
734
  <li><a href="${BASE}/apps/${a.id}/supporting-objects">${icon('database')} ${tx('app.task.supporting')}</a></li>
721
735
  <li><a href="#app-lock">${icon('lock')} ${tx('app.task.lock')}</a></li>
722
736
  ${issues.task}
723
- <li><a href="${BASE}/apps/${a.id}/settings?tab=definition">${icon('trash')} ${tx('app.task.delete')}</a></li>
724
737
  </ul></aside>
725
738
  </div>`;
726
739
  return send(reply, s, shell(s, a.name, [[tx('rte.app_builder'), BASE], [a.name]], main));
@@ -895,9 +908,13 @@ export async function builderRoutes(app: FastifyInstance) {
895
908
  ${await timeZoneSettings(a)}`)}${end}
896
909
  <div class="buttons settings-save"${['errors', 'pwa'].includes(tab) ? raw(' hidden') : ''}><button class="btn btn-hot">${tx('st.save_settings')}</button></div>
897
910
  </form>
898
- ${panel('definition')}<form method="post" action="${BASE}/apps/${a.id}/delete" class="danger-zone">${csrf(s)}
899
- <button class="btn btn-danger" data-confirm="${tx('st.delete_confirm', { app: a.name })}">${tx('st.delete')}</button>
900
- </form>${end}
911
+ ${panel('definition')}<section class="danger-zone danger-box" aria-labelledby="st-danger"><h2 id="st-danger">${tx('st.danger_zone')}</h2>
912
+ <p>${tx('st.delete_text', { app: a.name })} <a href="${BASE}/apps/${a.id}/export">${tx('app.head.export')}</a></p>
913
+ <!-- (UX-6) the alias typed to confirm, checked on the server too -->
914
+ <form method="post" action="${BASE}/apps/${a.id}/delete" class="danger-form">${csrf(s)}
915
+ <label class="field"><span class="label">${tx('st.delete_type', { alias: a.alias })}</span><input name="confirm" autocomplete="off" required spellcheck="false" pattern="${a.alias.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}"></label>
916
+ <button class="btn btn-danger">${icon('trash')} ${tx('st.delete')}</button>
917
+ </form></section>${end}
901
918
  ${panel('errors')}${region(tx('st.tab.errors'), html`<form method="post" action="${BASE}/apps/${a.id}/settings/behaviour">${csrf(s)}
902
919
  <div class="form-grid">
903
920
  ${input('error_function', tx('st.error_fn'), a.error_function ?? '', { placeholder: tx('st.error_fn_ph'),
@@ -1008,6 +1025,13 @@ export async function builderRoutes(app: FastifyInstance) {
1008
1025
  app.post(`${BASE}/apps/:id/delete`, async (req: Req, reply) => {
1009
1026
  const s = await developer(req, reply);
1010
1027
  if (!s) return;
1028
+ // (UX-6) only with the application's alias typed
1029
+ const target = await owner.one<{ alias: string }>('select alias from meta.app where id = $1', [Number(req.params.id) || 0]);
1030
+ if (!target) return reply.code(404).send('Not found');
1031
+ if (String(req.body?.confirm ?? '').trim() !== target.alias) {
1032
+ flash(s, tr(s)('st.delete_mismatch', { alias: target.alias }), 'error');
1033
+ return back(reply, s, `${BASE}/apps/${req.params.id}/settings?tab=definition`);
1034
+ }
1011
1035
  await owner.query('delete from meta.app where id = $1', [req.params.id]);
1012
1036
  flash(s, tr(s)('st.app_deleted'));
1013
1037
  return back(reply, s, BASE);