Resolve the page UI language once and let each ExApp fill its own Phrases.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-11 11:45:25 +02:00
co-authored by Cursor
parent afbd76445d
commit 623ada5f99
14 changed files with 1051 additions and 53 deletions
+36 -17
View File
@@ -2,18 +2,50 @@ package gonexapp
import (
_ "embed"
"html"
"html/template"
"net/http"
)
//go:embed dialog.js
var dialogJS string
// DialogHTML is the Dialog markup and script for an ExApp page.
// App navigation includes it. A page the ExApp renders itself inserts the
// same fragment. The page then calls exappDialog.message, exappDialog.confirm,
// DialogHTML is the Dialog markup and script for an ExApp page, in English.
// App navigation includes the same fragment in the UI language and does not
// take a language argument. A page the ExApp renders itself inserts this
// fragment, or Credentials.DialogHTML when that page has a request.
// The page then calls exappDialog.message, exappDialog.confirm,
// or exappDialog.prompt and waits for the user's choice.
func DialogHTML() template.HTML {
return template.HTML(dialogStyle + dialogMarkup + "<script>" + dialogJS + "</script>")
return dialogHTML("en")
}
// DialogHTML is the Dialog fragment in the UI language of r.
// A missing Requesting user or a failed read uses English.
// The caller does not pass a language.
func (c Credentials) DialogHTML(r *http.Request) template.HTML {
return dialogHTML(c.UILanguage(r))
}
func dialogHTML(lang string) template.HTML {
cancel := html.EscapeString(chromePhrase(lang, "dialog.cancel", nil))
agree := html.EscapeString(chromePhrase(lang, "dialog.ok", nil))
return template.HTML(dialogStyle + dialogButtons(cancel, agree) + "<script>" + dialogJS + "</script>")
}
func dialogButtons(cancel, agree string) string {
return `<dialog id="exapp-dialog" aria-modal="true">
<div id="exapp-dialog-panel">
<h2 id="exapp-dialog-heading" hidden></h2>
<p id="exapp-dialog-severity" hidden></p>
<p id="exapp-dialog-message"></p>
<input id="exapp-dialog-value" hidden autocomplete="off">
<div id="exapp-dialog-actions">
<button type="button" id="exapp-dialog-cancel">` + cancel + `</button>
<button type="button" id="exapp-dialog-agree">` + agree + `</button>
</div>
</div>
</dialog>`
}
const dialogStyle = `<style>
@@ -78,16 +110,3 @@ const dialogStyle = `<style>
}
#exapp-dialog-actions button#exapp-dialog-agree:disabled { opacity: 0.45; cursor: default; }
</style>`
const dialogMarkup = `<dialog id="exapp-dialog" aria-modal="true">
<div id="exapp-dialog-panel">
<h2 id="exapp-dialog-heading" hidden></h2>
<p id="exapp-dialog-severity" hidden></p>
<p id="exapp-dialog-message"></p>
<input id="exapp-dialog-value" hidden autocomplete="off">
<div id="exapp-dialog-actions">
<button type="button" id="exapp-dialog-cancel">Cancel</button>
<button type="button" id="exapp-dialog-agree">OK</button>
</div>
</div>
</dialog>`