| 1 | package gallery |
| 2 | |
| 3 | import "strings" |
| 4 | |
| 5 | // The gallery's own words: every label the chrome shows, by id. The |
| 6 | // examples' labels and markup are the manifest's and are not here. |
| 7 | // |
| 8 | // A value that still reads TODO-COPY:<id> has not been through copy |
| 9 | // review; TestTheGalleryCarriesNoPlaceholderCopy fails while any |
| 10 | // remains, so a placeholder cannot reach a page by accident. The ids |
| 11 | // are the ones the review is filed under. |
| 12 | // |
| 13 | // Most of what follows is Rastrillo's approved English, carried word |
| 14 | // for word from its gallery's prose table and its base catalog, with |
| 15 | // the id written beside it so the translation exporter can match the |
| 16 | // English against Rastrillo's rows. Fiesta's own strings are the ones |
| 17 | // part 3's review passed. |
| 18 | var text = map[string]string{ |
| 19 | // The <title> of every page: the page first, because a tab strip |
| 20 | // truncates from the end, then the site, then the theme. |
| 21 | "gallery.title": "{page} · Fiesta · {theme}", |
| 22 | // The brand link at the start of the header, back to the Overview. |
| 23 | "gallery.brand": "Fiesta", |
| 24 | // The skip link, first in every page. |
| 25 | "gallery.skip": "Skip to content", |
| 26 | // The theme switcher's accessible name. |
| 27 | "gallery.theme.label": "Theme", |
| 28 | |
| 29 | // The page kinds' titles, which name the pages, the rail's sections |
| 30 | // and the routes off the Overview. The families' titles are the |
| 31 | // prose's. |
| 32 | "gallery.kind.overview": "Overview", |
| 33 | "gallery.kind.tokens": "Tokens", |
| 34 | "gallery.kind.icons": "Icons", |
| 35 | "gallery.kind.getting-started": "Getting started", |
| 36 | // The Overview's route into the Tokens page. |
| 37 | "gallery.route.tokens": "Every custom property the system is built out of: the theme's colour and type, and the scales for size, spacing and radius.", |
| 38 | // The Overview: the heading over its routes. |
| 39 | "gallery.overview.next": "Where to go next", |
| 40 | // The Overview: its intro, and its routes into Getting started and the Icons page. |
| 41 | "gallery.overview.intro": "Fiesta is Rastrillo's design system as a project of its own: consistent, polished, accessible components for any website or app, in any stack or none, with no or minimal JavaScript, in twelve languages, in clean, modern HTML and CSS. One stylesheet and done; the markup is yours to copy and remix.", |
| 42 | "gallery.routes.getting-started": "What ships: the one-link stylesheet, each theme, the optional scripts and the strings, with what each file weighs.", |
| 43 | "gallery.routes.icons": "Every icon slug at the size components draw it, with the file to copy and its lucide.dev name.", |
| 44 | |
| 45 | // The previous and next pair at the foot of every page. |
| 46 | "gallery.step.prev": "Previous: {page}", |
| 47 | "gallery.step.next": "Next: {page}", |
| 48 | "gallery.steps.label": "Previous and next", |
| 49 | |
| 50 | // The rail: its accessible name, the Demos group, each section's |
| 51 | // overview item and the mark on a link that leaves the page. |
| 52 | "gallery.nav.sections": "Sections and demos", |
| 53 | "gallery.nav.demos": "Demos", |
| 54 | "gallery.nav.overview": "Overview", |
| 55 | "gallery.nav.overview.aria": "{section} overview", |
| 56 | "gallery.demos.shell": "The {shell} shell", |
| 57 | "gallery.demos.modal": "The modal route", |
| 58 | "gallery.demos.app": "The demo application", |
| 59 | "gallery.newtab": "opens in a new tab", |
| 60 | // The rail's filter. |
| 61 | "gallery.filter": "Filter", |
| 62 | "gallery.filter.empty": "No matches", |
| 63 | |
| 64 | // The display settings menu on a phone, and the language menu in it |
| 65 | // and in the bar. |
| 66 | "gallery.prefs": "Display settings", |
| 67 | "gallery.language": "Language", |
| 68 | "gallery.language.current": ", currently {language}", |
| 69 | "gallery.locale.name": "English", |
| 70 | // The way back from a content page on a phone: the shell's own |
| 71 | // words, from Rastrillo's base catalog. |
| 72 | "gallery.up": "Back to {name}", |
| 73 | "gallery.up.label": "Sections", |
| 74 | |
| 75 | // The preview widget: the tabs' legend and names, the HTML tab, |
| 76 | // the frame's accessible name, the Copy button and its live region, |
| 77 | // the wrapper line, and the note naming the routes a sample stands |
| 78 | // for. |
| 79 | "gallery.view.legend": "Preview", |
| 80 | "gallery.view.desktop": "Desktop", |
| 81 | "gallery.view.mobile": "Mobile", |
| 82 | "gallery.html": "HTML", |
| 83 | "gallery.frame.title": "{example}: {state}", |
| 84 | "gallery.copy": "Copy", |
| 85 | "gallery.copied": "Copied", |
| 86 | "gallery.copy.failed": "Copy failed. Select the code and copy it yourself.", |
| 87 | "gallery.wrap": "Put this inside {wrapper}.", |
| 88 | "gallery.routes": "In an app this would reach {routes}. Here its links and forms go nowhere.", |
| 89 | // An example's page: the two sentences under its heading. |
| 90 | "gallery.example.live": "Each example is live, but its links go nowhere.", |
| 91 | "gallery.example.html": "HTML shows the markup to copy.", |
| 92 | |
| 93 | // The demo application on the Overview, the shells' open buttons, |
| 94 | // and the way back from the demo and the modal route. |
| 95 | "gallery.demo.heading": "The demo application", |
| 96 | "gallery.demo.lead": "A working app built only from this system: a dashboard, a list, one record open. Each has its own address. No JavaScript.", |
| 97 | "gallery.demo.open": "Open the demo application", |
| 98 | "gallery.shell.open": "Open the {shell} shell", |
| 99 | "gallery.back": "Back to the design system", |
| 100 | // The primitives' live links. |
| 101 | "gallery.primitives.modal.live": "See it live at the URL it belongs to", |
| 102 | "gallery.primitives.sidebar.live": "Open the sidebar shell demo, a standalone preview.", |
| 103 | "gallery.primitives.topbar.live": "Open the topbar shell demo, a dedicated preview.", |
| 104 | // The demo application's request view: the body of its closing |
| 105 | // callout, Fiesta's own words under Rastrillo's title. |
| 106 | "gallery.demo.callout.body": "Each screen is a page of its own, plain HTML in the sidebar shell, and works the same with JavaScript off. On a phone, the sections are a list and each screen has a way back.", |
| 107 | |
| 108 | // The modal route: the page under it and the panel over it. |
| 109 | "gallery.modal.close": "Close settings", |
| 110 | "gallery.modal.own": "Modals get their own URL.", |
| 111 | "gallery.modal.settings": "Settings", |
| 112 | "gallery.modal.sub": "The page the modal opened over. It is marked inert, so nothing in here takes focus or reaches a screen reader while the panel is up.", |
| 113 | "gallery.modal.account": "Account", |
| 114 | "gallery.modal.profile": "Profile", |
| 115 | "gallery.modal.billing": "Billing", |
| 116 | "gallery.modal.notifications": "Notifications", |
| 117 | "gallery.modal.body": "Update the name and photo shown across the account.", |
| 118 | "gallery.modal.nojs": "Close link designed to work without JS.", |
| 119 | "gallery.modal.inapp": "In an application the ✕ would return you to the screen in the backdrop.", |
| 120 | |
| 121 | // Getting started: its headings, the weights table's note and line, |
| 122 | // and the per-file blurbs Rastrillo wrote for the files Fiesta |
| 123 | // ships too. |
| 124 | "gallery.started.stylesheets": "The stylesheets", |
| 125 | "gallery.started.scripts": "The scripts", |
| 126 | "gallery.started.weights": "What each file weighs", |
| 127 | "gallery.started.weights.note": "Sizes in KiB. Gzipped is what a visitor downloads.", |
| 128 | "gallery.started.weight": "{raw} as written · {gzip} gzipped · {stripped} gzipped without comments", |
| 129 | "gallery.started.upgrading": "Upgrading", |
| 130 | "gallery.started.file.tokens": "Structure: every component class, every scale, and no colour literal anywhere. The same file under every theme.", |
| 131 | "gallery.started.file.theme": "Colour, type family and shape for the {theme} theme: one :root block where every colour is declared once as a light-dark() pair.", |
| 132 | "gallery.started.file.shell-css": "The slide between pages on a phone, for the sidebar and console shells. Deletable with shell.js.", |
| 133 | "gallery.started.file.light-js": "The light the depth styles read: shadows lit by the hour, and a sheen on the button under the pointer. Delete it for the still design.", |
| 134 | "gallery.started.file.anchor-js": "Keeps a dropdown's menu on the screen in browsers without CSS anchor positioning. It does nothing where they have it: delete it once every browser you support does.", |
| 135 | "gallery.started.file.shell-js": "Phone navigation for the sidebar and console shells: the slide between pages, Back that reuses history, and focus returned to the section you left. Deletable on its own.", |
| 136 | "gallery.started.file.transition-js": "Prevents an error when the browser skips a page transition on column, stage and topbar pages. Load it before the stylesheets, without defer. Sidebar and console pages don't need it.", |
| 137 | "gallery.started.file.copy-js": "The snippet's Copy button: it copies the code, says Copied, and stays hidden where the browser has no clipboard. Deletable on its own.", |
| 138 | "gallery.started.file.select-js": "field-select's searchable combobox. Inert until a select opts in with data-rst-select, and deletable on its own.", |
| 139 | "gallery.started.file.datetime-js": "The date fields' natural-language input. Inert until a field opts in with data-rst-date or data-rst-time, and deletable on its own.", |
| 140 | "gallery.started.file.calendar-js": "The month grid that field's calendar button opens. Inert until datetime.js asks it for a panel, and deletable on its own: without it the button falls back to the browser's own picker.", |
| 141 | // Getting started: its lead, its sections' bodies and headings, the blurbs for Fiesta's own files, and the total. |
| 142 | "gallery.started.lead": "Fiesta is one stylesheet and a handful of optional scripts. Everything works with scripts off; the scripts are enhancements, each its own file, so you load the ones your page uses and nothing else.", |
| 143 | "gallery.started.stylesheets.body": "fiesta.css is tokens.css and the Day theme joined, comments stripped, under 25 KiB gzipped. The tokens hold every component's layout and behaviour; the theme paints them. fiesta-plain.css and fiesta-signal.css are the same tokens with the Plain and Signal themes. A page that uses the sidebar or console shell links shell.css as well; nothing else needs it.", |
| 144 | "gallery.started.scripts.body": "fiesta.js closes menus, lets a switch's knob be dragged, gives iOS its pressed state and runs the colour-scheme menu; load it first. busy.js, light.js, anchor.js, shell.js, transition.js, copy.js, select.js, datetime.js and calendar.js are each inert until a page uses what they enhance, and each deletable on its own. Load calendar.js last.", |
| 145 | "gallery.started.file.bundle": "Tokens and the {theme} theme in one file: every component class, every scale, and the colours, each declared once as a light-dark() pair.", |
| 146 | "gallery.started.file.fiesta-js": "The enhancements most pages want: menus that close on an outside click and on Escape, the switch's drag, iOS's pressed state, and the colour-scheme menu. Load it first.", |
| 147 | "gallery.started.file.busy-js": "The busy rule: while a form sends, its button shows a spinner for at least 650ms and refuses a second submit, and Back hands it back.", |
| 148 | "gallery.started.file.strings": "The words select.js, datetime.js and copy.js put on screen, in {language}. Load the one that matches your page's lang.", |
| 149 | "gallery.started.file.sprite": "A sprite with one symbol per icon, for a site that serves its own copy of Fiesta. From the CDN, inline the SVG from icons/<slug>.svg instead.", |
| 150 | "gallery.started.total": "A page that links fiesta.css and every script gets {raw} of CSS and JavaScript as written, {gzip} gzipped.", |
| 151 | "gallery.started.link.heading": "The one link", |
| 152 | "gallery.started.link.body": "Link fiesta.css from the CDN and your markup is styled. /1/ is the newest 1.x; a change that would break existing markup is a new major. Pin the exact version when you need bytes that never move.", |
| 153 | "gallery.started.own.heading": "Serving your own copy", |
| 154 | "gallery.started.own.body": "Take tokens.css and one theme, or the joined file, from a release and serve them with your site; the files under releases/<version>/ in the repository carry a SHA256SUMS. Link tokens.css first.", |
| 155 | "gallery.started.upgrading.body": "A page on /1/ picks up every 1.x release the day it ships; the changelog says what changed. A page pinned to an exact version moves when you change the link, and not before.", |
| 156 | |
| 157 | // The tokens page: lead, the note on the palette, and a heading per |
| 158 | // group of tokens.Group.Key. |
| 159 | "gallery.tokens.lead": "The custom properties every component reads. Colour, type family and shape come from the theme, css/themes/{theme}.css. The type scale and the spacing steps are structure, the same in every theme, and come from css/tokens.css.", |
| 160 | "gallery.tokens.note": "Light values shown. Every colour is declared once as a light-dark() pair, and the chips follow the scheme menu above. WCAG 2.2 AA floors: 4.5:1 for text, 3:1 for control borders.", |
| 161 | "gallery.tokens.group.surfaces-and-lines": "Surfaces and lines", |
| 162 | "gallery.tokens.group.text": "Text", |
| 163 | "gallery.tokens.group.accent": "Accent", |
| 164 | "gallery.tokens.group.status-tones": "Status tones", |
| 165 | "gallery.tokens.group.depth": "Depth", |
| 166 | "gallery.tokens.group.controls": "Controls", |
| 167 | "gallery.tokens.group.type-choices": "Type choices", |
| 168 | "gallery.tokens.group.radius": "Radius", |
| 169 | "gallery.tokens.group.type-family": "Type family", |
| 170 | "gallery.tokens.group.type-scale": "Type scale", |
| 171 | "gallery.tokens.group.spacing": "Spacing", |
| 172 | |
| 173 | // The icons page: its lead, and where the glyphs come from. |
| 174 | "gallery.icons.lead": "{total} icons from Lucide, each an inline SVG sized from the text beside it by tokens.css's own .icon rule, which is the size shown here.", |
| 175 | "gallery.icons.source": "Where the glyphs come from", |
| 176 | "gallery.icons.lucide": "The whole set is at {link}.", |
| 177 | "gallery.icons.kebab": "kebab and menu are the pair worth keeping straight: kebab is the three dots that mean more actions on this row, menu the three lines that mean navigation. The shells use menu when they collapse.", |
| 178 | // The Icons page: the section on the names, and the body of the section on the source. |
| 179 | "gallery.icons.names.heading": "The names are Fiesta's own", |
| 180 | "gallery.icons.names.body": "{renamed} of the {total} differ from the name lucide.dev publishes. Where the last line under an icon does not repeat its name, that is one of them. The names stay the same whatever a later icon set is drawn from.", |
| 181 | "gallery.icons.source.body": "Lucide, under the ISC licence, copied into the repository rather than fetched. The release carries the inline SVGs and a sprite; the gallery draws each one the way a component does.", |
| 182 | } |
| 183 | |
| 184 | // say returns the English filed under id, with each {name} replaced by |
| 185 | // the value following it in args. An id nothing is filed under is a |
| 186 | // programming error, not a page to render, so it panics: every id |
| 187 | // written in a template is one of the keys above. The pages read |
| 188 | // their words through site.say, which is this in the page's locale. |
| 189 | func say(id string, args ...string) string { |
| 190 | s, ok := text[id] |
| 191 | if !ok { |
| 192 | panic("gallery: no text for " + id) |
| 193 | } |
| 194 | return interpolate(s, args) |
| 195 | } |
| 196 | |
| 197 | // interpolate replaces each {name} in s with the value following it in |
| 198 | // args. An unmatched placeholder is left on the page rather than |
| 199 | // deleted, so a typo shows up as "{shel}" instead of half a sentence |
| 200 | // vanishing. |
| 201 | func interpolate(s string, args []string) string { |
| 202 | for i := 0; i+1 < len(args); i += 2 { |
| 203 | s = strings.ReplaceAll(s, "{"+args[i]+"}", args[i+1]) |
| 204 | } |
| 205 | return s |
| 206 | } |
| 207 | |