Saphan StudioDocs
Notifications

Languages and time

The two languages a binding can select, the two that are present but refused, how times are shown, and the one line you write yourself.

Language and time are properties of the destination, not of the fleet. Two teams reading two different conversations can read them in two different languages and two different timezones, from the same events.

Two languages you can select, and two you cannot

CodeLanguageCan a binding select it
enEnglishyes
plpolskiyes
arالعربية⛔ no — draft
thไทย⛔ no — draft

Set the one you want on the binding:

saphan config set notice.binding.ops.locale pl

A binding that names a draft catalogue is refused. The refusal happens where you set it, not at delivery time.

⚠ Read the last column as the whole answer. ar and th are present in the product as draft catalogues — part of their wording is still untranslated English — and ar is a right-to-left language. None of that makes them selectable: two are released, two are not.

The reason the draft ones are refused rather than allowed with a warning: a catalogue that is partly written renders a message that is partly in the language you chose and partly not, and the reader has no way to tell which half is the product's intention and which half is an unfinished translation. A notice in English is at least unambiguously in English.

What a catalogue holds

A catalogue holds the wording of a message in one language: the headline, the field labels, and the closing sentence that tells the reader what is now expected of them. A released catalogue carries that wording for every type in the table on What goes out; a draft one does not, and that incompleteness is the entire reason a binding cannot select a draft.

A catalogue also carries the binding's own fixed lines — the no-reply sentence and the reference line — and the words for each gate and decision, so a released language renders the whole notice, not only its headline.

Time: where a notice carries one, UTC and local together

notice.binding.<name>.timezone sets the local timezone for that binding:

saphan config set notice.binding.ops.timezone Europe/Warsaw

A time in a notice is shown in UTC and in that local zone, together. Not one or the other, and not one configurable instead of the other — both, wherever a time appears.

A third expression stands in front of that pair, and this key does not govern it. A notice also says how long ago the event happened, in words — 11 min ago — before the two clocks. It is not a timezone rendering, so this key does nothing to it, and no key on this page turns it off; it is there so a reader knows whether the thing in front of them is minutes old or a day old without doing arithmetic. ⚠ So "both" describes the pair of clocks, not the whole of the time on a notice.

⚠ A time is not on every notice. Every type in the table on What goes out carries the moment the event happened except delivery.failed, which declares no time field at all and prints no clock — so a plan to correlate a delivery failure by its timestamp is a plan built on something the product does not do. This key governs how a time is rendered where there is one — it does not put one on a notice that has none.

The reasons the pair is rendered rather than one of them:

  • UTC is the record's time. It is what the fleet stored, what an audit reads back, and it does not move twice a year. Someone comparing a notice against the record needs the notice to carry the same clock the record does.
  • Local is the reader's time. It is what tells a person on a Tuesday evening whether the thing that is waiting has been waiting ten minutes or since yesterday.

Showing one and letting the reader convert is where mistakes come from: a reader who converts in their head does it wrong at least once, and an auditor handed local times has to know where each reader was sitting before the timestamps mean anything. Carrying both costs a few characters and removes the question.

Your own line, and the rules it must obey

A binding can carry a line of your own — the sentence your readers see under a notice, telling them what this conversation is. That key is note:

saphan config set notice.binding.ops.note "Notices only — decisions are made in the console."

⚠ The neighbouring key is not a second sentence. notice.binding.<name>.no_reply_line is a switch: set it to true and the product adds its own line saying the conversation does not accept replies. You do not write that line's words, and writing a sentence into that key is not how you get one:

saphan config set notice.binding.ops.no_reply_line true

So: one key you fill in, one key you turn on. The five rules below are the rules of the one you fill in.

Five rules, and each of them is a refusal, named when you set the key:

The ruleWhy it is a rule
One line (binding-note-not-one-line)It is a line on a message, not a paragraph in it; any line break is refused.
At most 200 characters (binding-note-too-long)⛔ An over-long line is refused, never truncated. A truncated line is a sentence you did not write, appearing under your name, ending mid-word — and you would never see it, because you are not the one reading the notice.
No { or } (binding-note-is-a-template)The note is text, never a template; a brace is refused rather than ever filled in with a value the notice was not meant to publish.
No control character (binding-note-control-character)An invisible character in a line you cannot see the rendering of is a defect nobody can debug from the reading end.
Not blank (binding-note-blank)A note of nothing but spaces would render as an empty line. To remove the note, set it to the empty string.

The rule that matters most is the second one, and it is the one to read twice: the line is refused, never repaired. Nothing shortens it for you, nothing strips a character to make it fit. A line that is wrong is a line you are told about while you are still looking at it — which is the only moment anyone is looking at it, since the people who read the notices are not the people who set the key.

On this page