diff options
-rw-r--r-- | GNUmakefile | 5 | ||||
-rw-r--r-- | README.md | 13 | ||||
-rw-r--r-- | doc/i18n.md | 131 | ||||
-rwxr-xr-x | getfmt | 2 | ||||
-rw-r--r-- | src/i18n/i18n.go | 405 | ||||
-rw-r--r-- | src/templates/-404.html.tmpl | 2 | ||||
-rw-r--r-- | src/templates/-error.html.tmpl | 4 | ||||
-rw-r--r-- | src/templates/coins-designs-ad.html.tmpl | 4 | ||||
-rw-r--r-- | src/templates/coins-designs-de.html.tmpl | 63 | ||||
-rw-r--r-- | src/templates/coins-designs-hr.html.tmpl | 8 | ||||
-rw-r--r-- | src/templates/coins-designs-nl.html.tmpl | 48 | ||||
-rw-r--r-- | src/templates/coins-mintages.html.tmpl | 87 | ||||
-rw-r--r-- | static/designs/de-001.avif | bin | 0 -> 68749 bytes | |||
-rw-r--r-- | static/designs/de-010.avif | bin | 0 -> 80931 bytes | |||
-rw-r--r-- | static/designs/de-100.avif | bin | 0 -> 70964 bytes | |||
-rw-r--r-- | static/style.css | 110 |
16 files changed, 503 insertions, 379 deletions
diff --git a/GNUmakefile b/GNUmakefile index c69b87c..46c685b 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -13,14 +13,13 @@ all: euro-cash.eu exttmpl euro-cash.eu: $(cssfiles) $(templates) $(gofiles) $(sqlfiles) $(GO) build -all-i18n: exttmpl +po: exttmpl find . -name '*.html.tmpl' -exec ./exttmpl -out po/templates.pot {} + for bcp in en en-US nl; \ do \ mkdir -p "po/$$bcp"; \ msgmerge --update "po/$$bcp/messages.po" po/templates.pot; \ done - $(GO) build exttmpl: $(exttmpl) $(GO) build ./cmd/exttmpl @@ -41,4 +40,4 @@ clean: -or -name '*.tar.gz' \ \) -delete -.PHONY: all-i18n clean release
\ No newline at end of file +.PHONY: clean po release
\ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..17f4e4e --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +# euro-cash.eu — The Euro Cash Wiki + +This is the Git repository for the Euro Cash Wiki. This repository +contains everything to do with the website including the backend, +translations, etc. + +All documentation is located in the `doc/` directory. + +For translators: +- [Notes When Translating Pages](#) + +For programmers: +- [The Internationalization System](doc/i18n.md)
\ No newline at end of file diff --git a/doc/i18n.md b/doc/i18n.md new file mode 100644 index 0000000..475a512 --- /dev/null +++ b/doc/i18n.md @@ -0,0 +1,131 @@ +# The Internationalization System + +## Extracting Translations + +For translators to be able to translate text, and for us to be able to +work with those translations, we need translation files. These files are +located in the `/po` directory. These files are automatically generated +by running the `make po` command. In order to extract translations from +the source code, the `make po` command will search for calls to the +`Get()` family of functions, such as `Get()` and `GetN()`. + +```go +func example(n int) { + /* Not extracted for translation */ + fmt.Println("Hello, Sailor!") + + /* Extracted for translation */ + fmt.Println(i18n.GetN("1 book", "{N} books", n, + map[string]any{"N": n})) +} +``` + +Sometimes you want to provide additional context about a translation to +the translators. You can do this by placing a comment above the +translated string with the prefix ‘TRANSLATORS:’. + +```go +func example() string { + /* TRANSLATORS: ‘Home’ button on the navigation bar */ + return i18n.Get("Home") +} +``` + +Especially when working in HTML templates, you may have a string that you +want to go through the formatting system but _not_ be marked for +translation. You can do this by calling the underlying `Sprintf()` +function instead. + +```html +<p>{{ .Printer.Sprintf "{N:m}" (map "N" 2) }}</p> +``` + +## The Formatting System + +For string formatting we use a custom implementation of `Sprintf()`, and +all `Get*()` functions format the translated strings using our own +`Sprintf()`. + +Do note that all `Sprintf()` output is automatically HTML escaped. + +Unlike the standard `Sprintf()`, we use named placeholders enclosed by +curly braces instead of percent codes. As placeholders are named, they +need to be passed via a map of type `map[string]any`. + +```go +func example() { + status := "late" + + /* Go’s Sprintf */ + _ = fmt.Sprintf("The bus is %s", status) + + /* Our Sprintf */ + _ = i18n.Sprintf("The bus is {LateOrEarly}", + map[string]any{"LateOrEarly": status}) +} +``` + +The result is a lot more visually-noisy than what Go does — mostly due +to the map syntax — but it offers infinitely more information to +translators, which is important. + +Translation functions can be provided multiple argument maps, and maps +can be easily created in HTML templates using the `map` function. + +```html +{{ $nlargs := (map "DutchStart" `<span lang="nl"><em>` + "DutchEnd" `em,span`) }} +<p>{{ .Get "{Name} said ‘{DutchStart:r}{Quote}{DutchEnd:E}’!" + (map "Name" "Thomas" "Quote" "...") $nlargs }}</p> +``` + +In a placeholder you can also use a colon and additional character code +to customize how formatting is performed. The default behaviour is as +follows: + +- Strings are printed verbatim +- Numbers (`int`) and floats (`float64`) are formatted with the + locale-specific grouping- and decimal separators +- Dates (`time.Time`) are formatted according to the current locale +- Other types are coerced to a string by `fmt.Sprintf()` and then printed + verbatim + +The following character codes are available with the following behaviour: + +| Code | Mnemonic | Description | +| ---- | ------------------ | ----------------------------------------------------------- | +| `e` | \[e]mail | inserts a link to an email address | +| `E` | \[E]nd | inserts closing-tags for the comma-separated HTML tags | +| `l` | \[l]ink (internal) | links to an internal page | +| `L` | \[L]ink (external) | links to an external page | +| `m` | \[m]onetary | formats the given `int` or `float64` as an amount of Euros. | +| `r` | \[r]aw | inserts the given string verbatim without HTML escaping | + +```html +<!-- <a href="mailto:help@euro-cash.eu">help@euro-cash.eu</a> --> +<p>{{ .Get "{Email:e}" (map "Email" "help@euro-cash.eu") }}</p> + +<!-- <span lang="sv"><em>Växjösjön</em></span> --> +<p>{{ .Get "{SwedishStart:r}Växjösjön{SwedishEnd:E}" + (map "SwedishStart" `<span lang="sv"><em>` + "SwedishEnd" "em,span") }}</p> + +<!-- Click <a href="/banknotes">here</a>! --> +<p>{{ .Get "Click {Link:l}here{-:E}!" + (map "Link" "/banknotes") }}</p> + +<!-- Click <a href="https://euro-cash.eu" target="_blank">here</a>! --> +<p>{{ .Get "Click {Link:L}here{-:E}!" + (map "Link" "https://euro-cash.eu") }}</p> + +<!-- Varies per locale --> +<!-- €1 and €1.00 --> +<p>{{ .Get "{1:m} and {1.00:m}" (map "1" 1 "1.00" 1.00) }}</p> +``` + +Some additional notes: +- The `-` name is special. `{-:E}` inserts `</a>`. This exists because + of how often you need to do this. +- The `m` character code won’t include decimals when the argument is an + integer, and will include the decimals when the argument is a + floating-point number.
\ No newline at end of file @@ -24,7 +24,7 @@ date) ;; number) url='https://raw.githubusercontent.com/unicode-org/cldr-json/refs/heads/main/cldr-json/cldr-numbers-full/main/$l/numbers.json' - qry='.main.[$l].numbers.["decimalFormats-numberSystem-latn"].standard' + qry='"1\(.main.[$l].numbers.["symbols-numberSystem-latn"].group)234\(.main.[$l].numbers.["symbols-numberSystem-latn"].decimal)00"' ;; *) usage diff --git a/src/i18n/i18n.go b/src/i18n/i18n.go index 3bc490f..b996681 100644 --- a/src/i18n/i18n.go +++ b/src/i18n/i18n.go @@ -17,11 +17,12 @@ type Printer struct { } type LocaleInfo struct { - Bcp, Name string - Eurozone, Enabled bool - DateFormat string - ThousandsSeparator, DecimalSeparator rune - MonetaryPre, MonetaryPost [2]string + Bcp, Name string + Eurozone, Enabled bool + DateFormat string + GroupSeparator, DecimalSeparator rune + MonetaryPre [2]string + MonetaryPost string } type number interface { @@ -41,205 +42,267 @@ var ( 'r': sprintfr, } - /* To determine the correct date format to use, use the ‘datefmt’ script in - the repository root */ + /* To determine the correct currency-, date-, and number formats to + use, use the ‘getfmt’ script in the repository root */ locales = [...]LocaleInfo{ { - Bcp: "ca", - Name: "Català", - DateFormat: "2/1/2006", - Eurozone: true, - Enabled: false, + Bcp: "ca", + Name: "Català", + DateFormat: "2/1/2006", + Eurozone: true, + Enabled: false, + GroupSeparator: '.', + DecimalSeparator: ',', + MonetaryPre: [2]string{"", "-"}, + MonetaryPost: " €", }, { - Bcp: "de", - Name: "Deutsch", - DateFormat: "2.1.2006", - Eurozone: true, - Enabled: false, + Bcp: "de", + Name: "Deutsch", + DateFormat: "2.1.2006", + Eurozone: true, + Enabled: false, + GroupSeparator: '.', + DecimalSeparator: ',', + MonetaryPre: [2]string{"", "-"}, + MonetaryPost: " €", }, { - Bcp: "el", - Name: "Ελληνικά", - DateFormat: "2/1/2006", - Eurozone: true, - Enabled: true, + Bcp: "el", + Name: "Ελληνικά", + DateFormat: "2/1/2006", + Eurozone: true, + Enabled: true, + GroupSeparator: '.', + DecimalSeparator: ',', + MonetaryPre: [2]string{"", "-"}, + MonetaryPost: " €", }, { - Bcp: "en", - Name: "English", - DateFormat: "02/01/2006", - Eurozone: true, - Enabled: true, - ThousandsSeparator: ',', - DecimalSeparator: '.', - MonetaryPre: [2]string{"€", "-€"}, + Bcp: "en", + Name: "English", + DateFormat: "02/01/2006", + Eurozone: true, + Enabled: true, + GroupSeparator: ',', + DecimalSeparator: '.', + MonetaryPre: [2]string{"€", "-€"}, }, { - Bcp: "es", - Name: "Español", - DateFormat: "2/1/2006", - Eurozone: true, - Enabled: false, + Bcp: "es", + Name: "Español", + DateFormat: "2/1/2006", + Eurozone: true, + Enabled: false, + GroupSeparator: '.', + DecimalSeparator: ',', + MonetaryPre: [2]string{"", "-"}, + MonetaryPost: " €", }, { - Bcp: "et", - Name: "Eesti", - DateFormat: "2.1.2006", - Eurozone: true, - Enabled: false, + Bcp: "et", + Name: "Eesti", + DateFormat: "2.1.2006", + Eurozone: true, + Enabled: false, + GroupSeparator: ' ', + DecimalSeparator: ',', + MonetaryPre: [2]string{"", "-"}, + MonetaryPost: " €", }, { - Bcp: "fi", - Name: "Suomi", - DateFormat: "2.1.2006", - Eurozone: true, - Enabled: false, + Bcp: "fi", + Name: "Suomi", + DateFormat: "2.1.2006", + Eurozone: true, + Enabled: false, + GroupSeparator: ' ', + DecimalSeparator: ',', + MonetaryPre: [2]string{"", "-"}, + MonetaryPost: " €", }, { - Bcp: "fr", - Name: "Français", - DateFormat: "02/01/2006", - Eurozone: true, - Enabled: false, + Bcp: "fr", + Name: "Français", + DateFormat: "02/01/2006", + Eurozone: true, + Enabled: false, + GroupSeparator: ' ', + DecimalSeparator: ',', + MonetaryPre: [2]string{"", "-"}, + MonetaryPost: " €", }, { - Bcp: "ga", - Name: "Gaeilge", - DateFormat: "02/01/2006", - Eurozone: true, - Enabled: false, + Bcp: "ga", + Name: "Gaeilge", + DateFormat: "02/01/2006", + Eurozone: true, + Enabled: false, + GroupSeparator: ',', + DecimalSeparator: '.', + MonetaryPre: [2]string{"€", "-€"}, }, { - Bcp: "hr", - Name: "Hrvatski", - DateFormat: "02. 01. 2006.", - Eurozone: true, - Enabled: false, + Bcp: "hr", + Name: "Hrvatski", + DateFormat: "02. 01. 2006.", + Eurozone: true, + Enabled: false, + GroupSeparator: '.', + DecimalSeparator: ',', + MonetaryPre: [2]string{"", "-"}, + MonetaryPost: " €", }, { - Bcp: "it", - Name: "Italiano", - DateFormat: "02/01/2006", - Eurozone: true, - Enabled: false, + Bcp: "it", + Name: "Italiano", + DateFormat: "02/01/2006", + Eurozone: true, + Enabled: false, + GroupSeparator: '.', + DecimalSeparator: ',', + MonetaryPre: [2]string{"", "-"}, + MonetaryPost: " €", }, { - Bcp: "lb", - Name: "Lëtzebuergesch", - DateFormat: "2.1.2006", - Eurozone: true, - Enabled: false, + Bcp: "lb", + Name: "Lëtzebuergesch", + DateFormat: "2.1.2006", + Eurozone: true, + Enabled: false, + GroupSeparator: '.', + DecimalSeparator: ',', + MonetaryPre: [2]string{"", "-"}, + MonetaryPost: " €", }, { - Bcp: "lt", - Name: "Lietuvių", - DateFormat: "2006-01-02", - Eurozone: true, - Enabled: false, + Bcp: "lt", + Name: "Lietuvių", + DateFormat: "2006-01-02", + Eurozone: true, + Enabled: false, + GroupSeparator: ' ', + DecimalSeparator: ',', + MonetaryPre: [2]string{"", "-"}, + MonetaryPost: " €", }, { - Bcp: "lv", - Name: "Latviešu", - DateFormat: "2.01.2006.", - Eurozone: true, - Enabled: false, + Bcp: "lv", + Name: "Latviešu", + DateFormat: "2.01.2006.", + Eurozone: true, + Enabled: false, + GroupSeparator: ' ', + DecimalSeparator: ',', + MonetaryPre: [2]string{"", "-"}, + MonetaryPost: " €", }, { - Bcp: "mt", - Name: "Malti", - DateFormat: "2/1/2006", - Eurozone: true, - Enabled: false, + Bcp: "mt", + Name: "Malti", + DateFormat: "2/1/2006", + Eurozone: true, + Enabled: false, + GroupSeparator: ',', + DecimalSeparator: '.', + MonetaryPre: [2]string{"€", "-€"}, }, { - Bcp: "nl", - Name: "Nederlands", - DateFormat: "2-1-2006", - Eurozone: true, - Enabled: true, - ThousandsSeparator: '.', - DecimalSeparator: ',', - MonetaryPre: [2]string{"€ ", "€ -"}, + Bcp: "nl", + Name: "Nederlands", + DateFormat: "2-1-2006", + Eurozone: true, + Enabled: true, + GroupSeparator: '.', + DecimalSeparator: ',', + MonetaryPre: [2]string{"€ ", "€ -"}, }, { - Bcp: "pt", - Name: "Português", - DateFormat: "02/01/2006", - Eurozone: true, - Enabled: false, + Bcp: "pt", + Name: "Português", + DateFormat: "02/01/2006", + Eurozone: true, + Enabled: false, + GroupSeparator: '.', + DecimalSeparator: ',', + MonetaryPre: [2]string{"€ ", "€ -"}, }, { - Bcp: "sk", - Name: "Slovenčina", - DateFormat: "2. 1. 2006", - Eurozone: true, - Enabled: false, + Bcp: "sk", + Name: "Slovenčina", + DateFormat: "2. 1. 2006", + Eurozone: true, + Enabled: false, + GroupSeparator: ' ', + DecimalSeparator: ',', + MonetaryPre: [2]string{"", "-"}, + MonetaryPost: " €", }, { - Bcp: "sl", - Name: "Slovenščina", - DateFormat: "2. 1. 2006", - Eurozone: true, - Enabled: false, + Bcp: "sl", + Name: "Slovenščina", + DateFormat: "2. 1. 2006", + Eurozone: true, + Enabled: false, + GroupSeparator: '.', + DecimalSeparator: ',', + MonetaryPre: [2]string{"", "-"}, + MonetaryPost: " €", }, { - Bcp: "sv", - Name: "Svenska", - DateFormat: "2006-01-02", - Eurozone: true, - Enabled: false, + Bcp: "sv", + Name: "Svenska", + DateFormat: "2006-01-02", + Eurozone: true, + Enabled: false, + GroupSeparator: ' ', + DecimalSeparator: ',', + MonetaryPre: [2]string{"", "-"}, + MonetaryPost: " €", }, - /* Non-Eurozone locales */ { - Bcp: "bg", - Name: "Български", - DateFormat: "2.01.2006 г.", - Eurozone: false, /* TODO(2026): Set to true */ - Enabled: true, - }, - { - Bcp: "da", - Name: "Dansk", - DateFormat: "02.01.2006", - Eurozone: false, - Enabled: false, - }, - { - Bcp: "en-US", - Name: "English (US)", - DateFormat: "1/2/2006", - Eurozone: false, - Enabled: false, - }, - { - Bcp: "hu", - Name: "Magyar", - DateFormat: "2006. 01. 02.", - Eurozone: false, - Enabled: false, + Bcp: "bg", + Name: "Български", + DateFormat: "2.01.2006 г.", + Eurozone: false, /* TODO(2026): Set to true */ + Enabled: true, + GroupSeparator: ' ', + DecimalSeparator: ',', + MonetaryPre: [2]string{"", "-"}, + MonetaryPost: " €", }, { - Bcp: "pl", - Name: "Polski", - DateFormat: "2.01.2006", - Eurozone: false, - Enabled: false, + Bcp: "en-US", + Name: "English (US)", + DateFormat: "1/2/2006", + Eurozone: false, + Enabled: false, + GroupSeparator: ',', + DecimalSeparator: '.', + MonetaryPre: [2]string{"€", "-€"}, }, { - Bcp: "ro", - Name: "Română", - DateFormat: "02.01.2006", - Eurozone: false, - Enabled: false, + Bcp: "ro", + Name: "Română", + DateFormat: "02.01.2006", + Eurozone: false, + Enabled: false, + GroupSeparator: '.', + DecimalSeparator: ',', + MonetaryPre: [2]string{"", "-"}, + MonetaryPost: " €", }, { - Bcp: "uk", - Name: "Yкраїнська", - DateFormat: "02.01.2006", - Eurozone: false, - Enabled: false, + Bcp: "uk", + Name: "Yкраїнська", + DateFormat: "02.01.2006", + Eurozone: false, + Enabled: false, + GroupSeparator: ' ', + DecimalSeparator: ',', + MonetaryPre: [2]string{"", "-"}, + MonetaryPost: " €", }, } /* Map of language codes to printers. We do this instead of just @@ -280,7 +343,7 @@ func (l LocaleInfo) Language() string { func (p Printer) Sprintf(format string, args ...map[string]any) string { var bob strings.Builder vars := map[string]any{ - "-": "", + "-": "a", } for _, arg := range args { maps.Copy(vars, arg) @@ -347,9 +410,9 @@ func sprintfGeneric(li LocaleInfo, bob *strings.Builder, v any) error { case time.Time: htmlesc(bob, v.(time.Time).Format(li.DateFormat)) case int: - writeInt(bob, v.(int), li.ThousandsSeparator) + writeInt(bob, v.(int), li.GroupSeparator) case float64: - writeFloat(bob, v.(float64), li.ThousandsSeparator, li.DecimalSeparator) + writeFloat(bob, v.(float64), li.GroupSeparator, li.DecimalSeparator) case string: htmlesc(bob, v.(string)) default: @@ -371,8 +434,16 @@ func sprintfe(li LocaleInfo, bob *strings.Builder, v any) error { return nil } -func sprintfE(li LocaleInfo, bob *strings.Builder, _ any) error { - bob.WriteString("</a>") +func sprintfE(li LocaleInfo, bob *strings.Builder, v any) error { + s, ok := v.(string) + if !ok { + return errors.New("TODO") + } + for tag := range strings.SplitSeq(s, ",") { + bob.WriteString("</") + bob.WriteString(tag) + bob.WriteByte('>') + } return nil } @@ -402,16 +473,14 @@ func sprintfm(li LocaleInfo, bob *strings.Builder, v any) error { switch v.(type) { case int: n := v.(int) - i := btoi(n >= 0) - htmlesc(bob, li.MonetaryPre[i]) - writeInt(bob, abs(n), li.ThousandsSeparator) - htmlesc(bob, li.MonetaryPost[i]) + htmlesc(bob, li.MonetaryPre[btoi(n >= 0)]) + writeInt(bob, abs(n), li.GroupSeparator) + htmlesc(bob, li.MonetaryPost) case float64: n := v.(float64) - i := btoi(n >= 0) - htmlesc(bob, li.MonetaryPre[i]) - writeFloat(bob, abs(n), li.ThousandsSeparator, li.DecimalSeparator) - htmlesc(bob, li.MonetaryPost[i]) + htmlesc(bob, li.MonetaryPre[btoi(n >= 0)]) + writeFloat(bob, abs(n), li.GroupSeparator, li.DecimalSeparator) + htmlesc(bob, li.MonetaryPost) default: return errors.New("TODO") } diff --git a/src/templates/-404.html.tmpl b/src/templates/-404.html.tmpl index 06ac02b..03602e1 100644 --- a/src/templates/-404.html.tmpl +++ b/src/templates/-404.html.tmpl @@ -5,7 +5,7 @@ </header> <main> <p> - {{ .Get "The page you were looking for does not exist. If you believe this is a mistake then don’t hesitate to contact ‘@onetruemangoman’ on Discord or email us at %(Email:e)." + {{ .Get "The page you were looking for does not exist. If you believe this is a mistake then don’t hesitate to contact ‘@onetruemangoman’ on Discord or email us at {Email:e}." (map "Email" "mail@euro-cash.eu") }} </p> </main> diff --git a/src/templates/-error.html.tmpl b/src/templates/-error.html.tmpl index 5b8258b..a18ec3e 100644 --- a/src/templates/-error.html.tmpl +++ b/src/templates/-error.html.tmpl @@ -8,8 +8,8 @@ {{ .Get "If you’re seeing this page, it means that something went wrong on our end that we need to fix. Our team has been notified of this error, and we apologise for the inconvenience." }} </p> <p> - {{ .Get "If this issue persists, don’t hesitate to contact ‘@onetruemangoman’ on Discord or to email us at %(Email:e)" - (map "Email" "mail@euro-cash.eu") }} + {{ .Get "If this issue persists, don’t hesitate to contact ‘@onetruemangoman’ on Discord or to email us at {Email:e}" + (map "Email" "mail@euro-cash.eu") }} </p> </main> {{ end }}
\ No newline at end of file diff --git a/src/templates/coins-designs-ad.html.tmpl b/src/templates/coins-designs-ad.html.tmpl index ab27555..d63110c 100644 --- a/src/templates/coins-designs-ad.html.tmpl +++ b/src/templates/coins-designs-ad.html.tmpl @@ -44,8 +44,8 @@ <li>{{ .Get "The arms of Catalonia" }}</li> <li>{{ .Get "The arms of the Viscounts of Béarn" }}</li> </ul> - {{ .Get "The bottom of the coat of arms has the motto ‘{LatinStart:r}VIRTVS VNITA FORTIOR{LatinEnd:r}’ (English: ‘UNITED VIRTUE IS STRONGER’)." - (map "LatinStart" `<span lang="la"><em>` "LatinEnd" `</em></span>`) }} + {{ .Get "The bottom of the coat of arms has the motto ‘{LatinStart:r}VIRTVS VNITA FORTIOR{LatinEnd:E}’ (English: ‘UNITED VIRTUE IS STRONGER’)." + (map "LatinStart" `<span lang="la"><em>` "LatinEnd" "em,span") }} </p> </main> {{ end }}
\ No newline at end of file diff --git a/src/templates/coins-designs-de.html.tmpl b/src/templates/coins-designs-de.html.tmpl new file mode 100644 index 0000000..995752f --- /dev/null +++ b/src/templates/coins-designs-de.html.tmpl @@ -0,0 +1,63 @@ +{{ define "content" }} +<header> + {{ template "navbar" . }} + <h1>{{ .Get "German Euro Coin Designs" }}</h1> +</header> +<main> + {{ $deargs := (map "GermanStart" `<span lang="de"><em>` "GermanEnd" "em,span") }} + + <div class="design-container"> + <img alt="{{ .Get `German €0.01 coin` }}" src="/designs/de-001.avif"> + <img alt="{{ .Get `German €0.10 coin` }}" src="/designs/de-010.avif"> + <img alt="{{ .Get `German €1 coin` }}" src="/designs/de-100.avif"> + </div> + <p> + {{ .Get "The German euro coins feature three different designs. A unique feature of German euro coins are the mint marks on each coin that denote in which city a given coin was minted. Germany has five active mints that produce Euro coins, which are denoted in the table below." }} + </p> + + <table> + <thead> + <tr> + <th>{{ .Get "City" }}</th> + <th>{{ .Get "Mintmark" }}</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{ .Get "Berlin" }}</td> + <td>A</td> + </tr> + <tr> + <td>{{ .Get "Munich" }}</td> + <td>D</td> + </tr> + <tr> + <td>{{ .Get "Stuttgart" }}</td> + <td>F</td> + </tr> + <tr> + <td>{{ .Get "Karlsruhe" }}</td> + <td>G</td> + </tr> + <tr> + <td>{{ .Get "Hamburg" }}</td> + <td>J</td> + </tr> + </tbody> + </table> + + <p> + {{ .Get "The bronze coins display an oak twig which is similar to the one found on the former Pfennig coins from the German Mark. The mint mark and year are located on the left- and right-hand sides of the stem." }} + </p> + <p> + {{ .Get "The gold coins feature the Brandenburg Gate, a symbol of Berlin and Germany as a whole, but also a symbol of German division and unity. The mint mark is located below the year." }} + </p> + <p> + {{ .Get "The bimetallic coins feature an interpretation of the German Federal Eagle (German: ‘{GermanStart:r}Bundesadler{GermanEnd:E}’). The eagle is a common motif in German heraldry — including in the German coat of arms — and represents strength and freedom. The mint mark is located to the right of the year." $deargs }} + </p> + <p> + <!-- TODO: Get a picture of the edge-inscription --> + {{ .Get "The €2 coin also features an edge-inscription of Germany’s national motto and incipit of Germany’s national anthem. It reads ‘{GermanStart:r}EINIGKEIT UND RECHT UND FREIHEIT{GermanEnd:E}’ (English: ‘UNITY AND JUSTICE AND FREEDOM’)." $deargs }} + </p> +</main> +{{ end }}
\ No newline at end of file diff --git a/src/templates/coins-designs-hr.html.tmpl b/src/templates/coins-designs-hr.html.tmpl index 3c8fae5..9f98a9b 100644 --- a/src/templates/coins-designs-hr.html.tmpl +++ b/src/templates/coins-designs-hr.html.tmpl @@ -4,7 +4,7 @@ <h1>{{ .Get "Croatian Euro Coin Designs" }}</h1> </header> <main> - {{ $hrargs := (map "CroatianStart" `<span lang="hr"><em>` "CroatianEnd" `</em></span>`) }} + {{ $hrargs := (map "CroatianStart" `<span lang="hr"><em>` "CroatianEnd" "em,span") }} <div class="design-container"> <img alt="{{ .Get `Croatian €0.01 coin` }}" src="/designs/hr-001.avif" /> <img alt="{{ .Get `Croatian €0.50 coin` }}" src="/designs/hr-050.avif" /> @@ -14,7 +14,7 @@ <img alt="{{ .Get `Croatian €2 coin` }}" src="/designs/hr-200.avif" /> </div> <p> - {{ .Get "The Croatian euro coins feature four different themes, with each design featuring the Croatian checkerboard and the country’s name in Croatian (‘{CroatianStart:r}HRVATSKA{CroatianEnd:r}’). All designs were selected after voting in a public design competition." + {{ .Get "The Croatian euro coins feature four different themes, with each design featuring the Croatian checkerboard and the country’s name in Croatian (‘{CroatianStart:r}HRVATSKA{CroatianEnd:E}’). All designs were selected after voting in a public design competition." $hrargs }} </p> <p> @@ -26,12 +26,12 @@ (map "Link" "https://www.wikipedia.org/wiki/Nikola_Tesla") }} </p> <p> - {{ .Get "The 1 euro coin was designed by Jagor Šunde, David Čemeljić and Fran Zekan and features a marten. The marten is the semi-official national animal of Croatia and the Kuna — their pre-Euro currency — was named after the marten (‘{CroatianStart:r}kuna zlatica{CroatianEnd:r}’ in Croatian)." + {{ .Get "The 1 euro coin was designed by Jagor Šunde, David Čemeljić and Fran Zekan and features a marten. The marten is the semi-official national animal of Croatia and the Kuna — their pre-Euro currency — was named after the marten (‘{CroatianStart:r}kuna zlatica{CroatianEnd:E}’ in Croatian)." $hrargs }} </p> <p> <!-- TODO: Include a photo of the edge inscription --> - {{ .Get "The 2 euro coin was designed by Ivan Šivak and features the map of Croatia. The coin also has an edge-inscription that reads ‘{CroatianStart:r}O LIJEPA O DRAGA O SLATKA SLOBODO{CroatianEnd:r}’ (English: ‘OH BEAUTIFUL, OH DEAR, OH SWEET FREEDOM’) which is a line from the play {Link:L}Dubravka{-:E} by Ivan Gundulić." + {{ .Get "The 2 euro coin was designed by Ivan Šivak and features the map of Croatia. The coin also has an edge-inscription that reads ‘{CroatianStart:r}O LIJEPA O DRAGA O SLATKA SLOBODO{CroatianEnd:E}’ (English: ‘OH BEAUTIFUL, OH DEAR, OH SWEET FREEDOM’) which is a line from the play {Link:L}Dubravka{-:E} by Ivan Gundulić." $hrargs (map "Link" "https://www.wikipedia.org/wiki/Dubravka_(drama)") }} </p> </main> diff --git a/src/templates/coins-designs-nl.html.tmpl b/src/templates/coins-designs-nl.html.tmpl index 2395480..e98e77b 100644 --- a/src/templates/coins-designs-nl.html.tmpl +++ b/src/templates/coins-designs-nl.html.tmpl @@ -1,65 +1,41 @@ {{ define "content" }} <header> {{ template "navbar" . }} - <h1>{{ .T "Dutch Euro Coin Designs" }}</h1> + <h1>{{ .Get "Dutch Euro Coin Designs" }}</h1> </header> <main> - {{ $dutchStart := `<span lang="nl">` }} - {{ $dutchEnd := `</span>` }} + {{ $nlargs := (map "DutchStart" `<span lang="nl"><em>` "DutchEnd" "em,span") }} <div class="design-container"> <img - alt="Dutch 50 euro cent coin (Beatrix)" + alt="Dutch €0.50 coin (Queen Beatrix)" src="/designs/nl-050-beatrix.avif" /> <img - alt="Dutch 50 euro cent coin (Willem-Alexander)" + alt="Dutch €0.50 coin (King Willem-Alexander)" src="/designs/nl-050-willem-alexander.avif" /> </div> <div class="design-container"> <img - alt="Dutch 1 euro coin (Beatrix)" + alt="Dutch €1 coin (Queen Beatrix)" src="/designs/nl-100-beatrix.avif" /> <img - alt="Dutch 1 euro coin (Willem-Alexander)" + alt="Dutch €1 coin (King Willem-Alexander)" src="/designs/nl-100-willem-alexander.avif" /> </div> <p> - {{ .T ` - From the years 1999–2013 all Dutch euro coins featured the portrait - of Queen Beatrix of the Netherlands. After her abdication from the - throne in 2013 the designs of all denominations were changed to - feature the portrait of the new King Willem-Alexander. After her - abdication the direction in which the monarchs portrait faced was - flipped; a tradition dating back to the earliest coins of the - Kingdom of the Netherlands. - ` }} + {{ .Get "From the years 1999–2013 all Dutch euro coins featured the portrait of Queen Beatrix of the Netherlands. After her abdication from the throne in 2013 the designs of all denominations were changed to feature the portrait of the new King Willem-Alexander. After her abdication the direction in which the monarchs portrait faced was flipped; a tradition shared by the coins of many monarchies around the world." }} </p> <p> <!-- TODO: Get a picture of the edge-inscription --> - {{ .T ` - Coins featuring both monarchs contain text reading ‘%sBEATRIX - KONINGIN DER NEDERLANDEN%s’ (‘BEATRIX QUEEN OF THE - NETHERLANDS’) and ‘%sWillem-Alexander Koning der - Nederlanden%s’ (‘Willem-Alexander King of the Netherlands’) - respectively. The €2 coins also feature an edge-inscription - reading ‘%sGOD ⋆ ZIJ ⋆ MET ⋆ ONS ⋆%s’ - (‘GOD ⋆ IS ⋆ WITH ⋆ US ⋆’). - ` - $dutchStart $dutchEnd - $dutchStart $dutchEnd - $dutchStart $dutchEnd | safe }} + {{ .Get "Coins featuring both monarchs contain text reading ‘{DutchStart:r}BEATRIX KONINGIN DER NEDERLANDEN{DutchEnd:E}’ (English: ‘BEATRIX QUEEN OF THE NETHERLANDS’) and ‘{DutchStart:r}Willem-Alexander Koning der Nederlanden{DutchEnd:E}’ (English: ‘Willem-Alexander King of the Netherlands’) respectively. The €2 coins also feature an edge-inscription reading ‘{DutchStart:r}GOD ⋆ ZIJ ⋆ MET ⋆ ONS ⋆{DutchEnd:E}’ (English: ‘GOD ⋆ IS ⋆ WITH ⋆ US ⋆’)." + $nlargs }} </p> <p> - {{ .T ` - The €1 and €2 coins featuring King Willem-Alexander were minted - with a much lower %srelief%s than most euro coins of the same - denomination. As a result it is not uncommon for these coins to - appear worn after little use in circulation.` - `<a href="/jargon#relief">` `</a>` | safe - }} + {{ .Get "The €1 and €2 coins featuring King Willem-Alexander were minted with a much lower {Link:l}relief{-:E} than most euro coins of the same denomination. As a result it is not uncommon for these coins to appear worn after little use in circulation." + (map "Link" "/jargon#relief") }} </p> </main> -{{ end }} +{{ end }}
\ No newline at end of file diff --git a/src/templates/coins-mintages.html.tmpl b/src/templates/coins-mintages.html.tmpl index 1cf7c70..8df0868 100644 --- a/src/templates/coins-mintages.html.tmpl +++ b/src/templates/coins-mintages.html.tmpl @@ -1,38 +1,19 @@ {{ define "content" }} <header> {{ template "navbar" . }} - <h1>{{ .T "Euro Coin Mintages" }}</h1> + <h1>{{ .Get "Euro Coin Mintages" }}</h1> </header> <main> <p> - {{ .T ` - Here you’ll be able to view all the known mintages for all - coins. You’ll also be able to filter on country, denomination, - etc. If you have any mintage data that’s missing from our site, - feel free to contact us. - ` }} + {{ .Get "Here you’ll be able to view all the known mintages for all coins. You’ll also be able to filter on country, denomination, etc. If you have any mintage data that’s missing from our site, feel free to contact us." }} </p> <hr /> {{ if eq .Code "nl" }} - <h2>{{ .T "Additional Notes" }}</h2> + <h2>{{ .Get "Additional Notes" }}</h2> <ul> <li> - {{ .T ` - Most coins from the years 2003–2016 are listed as NIFC coins - while other popular sources such as Numista claim they were - minted for circulation. For more information on why others are - wrong, %sclick here%s.` - `<a href="#TODO">` `</a>` | safe - }} - </li> - <li> - {{ .T ` - In 2003 Numista calculated a total of %d coins issued for coin - sets per denomination. Our own calculations found only - %d. Numista also forgot to include the many hundred thousand - coins from the coin roll sets that were produced.` - 217503 177003 - }} + {{ .Get "Most coins from the years 2003–2016 are listed as NIFC coins while other popular sources such as Numista claim they were minted for circulation. For more information on why others are wrong, {Link:l}click here{-:E}." + (map "Link" "#TODO") }} </li> </ul> {{ end }} @@ -40,12 +21,12 @@ <form> <div class="grid"> <label for="country-dd"> - {{ .T "Country" }} + {{ .Get "Country" }} <select id="country-dd" name="code"> {{ $code := .Code }} {{ range .Countries }} <option - value={{ .Code }} + value="{{ .Code }}" {{ if eq .Code $code }} selected {{ end }} @@ -57,28 +38,28 @@ </label> <fieldset> {{ template "coin-type-radio" - (tuple .Type "circ" (.T "Circulation Coins")) }} + (tuple .Type "circ" (.Get "Circulation Coins")) }} {{ template "coin-type-radio" - (tuple .Type "nifc" (.T "NIFC / BU Sets")) }} + (tuple .Type "nifc" (.Get "NIFC / BU Sets")) }} {{ template "coin-type-radio" - (tuple .Type "proof" (.T "Proof Coins")) }} + (tuple .Type "proof" (.Get "Proof Coins")) }} </fieldset> </div> - <button type="submit">{{ .T "Filter" }}</button> + <button type="submit">{{ .Get "Filter" }}</button> </form> <figure> - <figcaption>{{ .T "Standard Issue Coins" }}</figcaption> + <figcaption>{{ .Get "Standard Issue Coins" }}</figcaption> <table class="mintage-table" role="grid"> <thead> - <th>{{ .T "Year" }}</th> - <th>{{ .M 0.01 }}</th> - <th>{{ .M 0.02 }}</th> - <th>{{ .M 0.05 }}</th> - <th>{{ .M 0.10 }}</th> - <th>{{ .M 0.20 }}</th> - <th>{{ .M 0.50 }}</th> - <th>{{ .M 1.00 }}</th> - <th>{{ .M 2.00 }}</th> + <th>{{ .Get "Year" }}</th> + <th>{{ .Printer.Sprintf "{N:m}" (map "N" 0.01) }}</th> + <th>{{ .Printer.Sprintf "{N:m}" (map "N" 0.02) }}</th> + <th>{{ .Printer.Sprintf "{N:m}" (map "N" 0.05) }}</th> + <th>{{ .Printer.Sprintf "{N:m}" (map "N" 0.10) }}</th> + <th>{{ .Printer.Sprintf "{N:m}" (map "N" 0.20) }}</th> + <th>{{ .Printer.Sprintf "{N:m}" (map "N" 0.50) }}</th> + <th>{{ .Printer.Sprintf "{N:m}" (map "N" 1.00) }}</th> + <th>{{ .Printer.Sprintf "{N:m}" (map "N" 2.00) }}</th> </thead> <tbody> {{ $p := .Printer }} @@ -92,13 +73,13 @@ </th> {{ range .Mintages }} {{ if eq . -1 }} - <td>{{ $p.T "Unknown" }}</td> + <td>{{ $p.Get "Unknown" }}</td> {{ else if eq . -2 }} - <td class="error">{{ $p.T "Error" }}</td> + <td class="error">{{ $p.Get "Error" }}</td> {{ else if eq . 0 }} <td>—</td> {{ else }} - <td>{{ $p.N . }}</td> + <td>{{ $p.Sprintf "{N}" (map "N" .) }}</td> {{ end }} </td> {{ end }} @@ -109,12 +90,12 @@ </figure> {{ if ne (len .Mintages.Commemorative) 0 }} <figure> - <figcaption>{{ .T "Commemorative Coins" }}</figcaption> + <figcaption>{{ .Get "Commemorative Coins" }}</figcaption> <table class="mintage-table-cc" role="grid"> <thead> - <th>{{ .T "Year" }}</th> - <th>{{ .T "Commemorated Issue" }}</th> - <th>{{ .T "Mintage" }}</th> + <th>{{ .Get "Year" }}</th> + <th>{{ .Get "Commemorated Issue" }}</th> + <th>{{ .Get "Mintage" }}</th> </thead> <tbody> {{ $p := .Printer }} @@ -130,13 +111,13 @@ <td>{{ .Name }}</td> {{ with .Mintage }} {{ if eq . -1 }} - <td>{{ $p.T "Unknown" }}</td> + <td>{{ $p.Get "Unknown" }}</td> {{ else if eq . -2 }} - <td class="error">{{ $p.T "Error" }}</td> + <td class="error">{{ $p.Get "Error" }}</td> {{ else if eq . 0 }} <td>—</td> {{ else }} - <td>{{ $p.N . }}</td> + <td>{{ $p.Sprintf "{N}" (map "N" .) }}</td> {{ end }} {{ end }} </tr> @@ -150,12 +131,12 @@ {{ end }} {{ define "coin-type-radio" }} -<label for={{ index . 1 }}> +<label for="{{ index . 1 }}"> <input - id={{ index . 1 }} + id="{{ index . 1 }}" name="type" type="radio" - value={{ index . 1 }} + value="{{ index . 1 }}" {{ if eq (index . 0) (index . 1) }} checked {{ end }} diff --git a/static/designs/de-001.avif b/static/designs/de-001.avif Binary files differnew file mode 100644 index 0000000..0e368c1 --- /dev/null +++ b/static/designs/de-001.avif diff --git a/static/designs/de-010.avif b/static/designs/de-010.avif Binary files differnew file mode 100644 index 0000000..563d09c --- /dev/null +++ b/static/designs/de-010.avif diff --git a/static/designs/de-100.avif b/static/designs/de-100.avif Binary files differnew file mode 100644 index 0000000..6fd39fd --- /dev/null +++ b/static/designs/de-100.avif diff --git a/static/style.css b/static/style.css index 2bce9d4..8d8bc5b 100644 --- a/static/style.css +++ b/static/style.css @@ -188,8 +188,7 @@ tfoot td { --font-size: 0.875em; } -[data-theme=light], -:root:not([data-theme=dark]) { +[data-theme=light] { --background-color: #fff; --color: hsl(205, 20%, 32%); --h1-color: hsl(205, 30%, 15%); @@ -294,113 +293,6 @@ tfoot td { color-scheme: light; } -@media only screen and (prefers-color-scheme: dark) { - :root:not([data-theme]) { - --background-color: #11191f; - --color: hsl(205, 16%, 77%); - --h1-color: hsl(205, 20%, 94%); - --h2-color: #e1e6eb; - --h3-color: hsl(205, 18%, 86%); - --h4-color: #c8d1d8; - --h5-color: hsl(205, 16%, 77%); - --h6-color: #afbbc4; - --muted-color: hsl(205, 10%, 50%); - --muted-border-color: #1f2d38; - --primary: hsl(195, 85%, 41%); - --primary-hover: hsl(195, 80%, 50%); - --primary-focus: rgba(16, 149, 193, 0.25); - --primary-inverse: #fff; - --secondary: hsl(205, 15%, 41%); - --secondary-hover: hsl(205, 10%, 50%); - --secondary-focus: rgba(115, 130, 140, 0.25); - --secondary-inverse: #fff; - --contrast: hsl(205, 20%, 94%); - --contrast-hover: #fff; - --contrast-focus: rgba(115, 130, 140, 0.25); - --contrast-inverse: #000; - --mark-background-color: #d1c284; - --mark-color: #11191f; - --ins-color: #388e3c; - --del-color: #c62828; - --blockquote-border-color: var(--muted-border-color); - --blockquote-footer-color: var(--muted-color); - --button-box-shadow: 0 0 0 rgba(0, 0, 0, 0); - --button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0); - --form-element-background-color: #11191f; - --form-element-border-color: #374956; - --form-element-color: var(--color); - --form-element-placeholder-color: var(--muted-color); - --form-element-active-background-color: var(--form-element-background-color); - --form-element-active-border-color: var(--primary); - --form-element-focus-color: var(--primary-focus); - --form-element-disabled-background-color: hsl(205, 25%, 23%); - --form-element-disabled-border-color: hsl(205, 20%, 32%); - --form-element-disabled-opacity: 0.5; - --form-element-invalid-border-color: #b71c1c; - --form-element-invalid-active-border-color: #c62828; - --form-element-invalid-focus-color: rgba(198, 40, 40, 0.25); - --form-element-valid-border-color: #2e7d32; - --form-element-valid-active-border-color: #388e3c; - --form-element-valid-focus-color: rgba(56, 142, 60, 0.25); - --switch-background-color: #374956; - --switch-color: var(--primary-inverse); - --switch-checked-background-color: var(--primary); - --range-border-color: #24333e; - --range-active-border-color: hsl(205, 25%, 23%); - --range-thumb-border-color: var(--background-color); - --range-thumb-color: var(--secondary); - --range-thumb-hover-color: var(--secondary-hover); - --range-thumb-active-color: var(--primary); - --table-border-color: var(--muted-border-color); - --table-row-stripped-background-color: rgba(115, 130, 140, 0.05); - --code-background-color: #18232c; - --code-color: var(--muted-color); - --code-kbd-background-color: var(--contrast); - --code-kbd-color: var(--contrast-inverse); - --code-tag-color: hsl(330, 30%, 50%); - --code-property-color: hsl(185, 30%, 50%); - --code-value-color: hsl(40, 10%, 50%); - --code-comment-color: #4d606d; - --accordion-border-color: var(--muted-border-color); - --accordion-active-summary-color: var(--primary); - --accordion-close-summary-color: var(--color); - --accordion-open-summary-color: var(--muted-color); - --card-background-color: #141e26; - --card-border-color: var(--card-background-color); - --card-box-shadow: - 0.0145rem 0.029rem 0.174rem rgba(0, 0, 0, 0.01698), - 0.0335rem 0.067rem 0.402rem rgba(0, 0, 0, 0.024), - 0.0625rem 0.125rem 0.75rem rgba(0, 0, 0, 0.03), - 0.1125rem 0.225rem 1.35rem rgba(0, 0, 0, 0.036), - 0.2085rem 0.417rem 2.502rem rgba(0, 0, 0, 0.04302), - 0.5rem 1rem 6rem rgba(0, 0, 0, 0.06), - 0 0 0 0.0625rem rgba(0, 0, 0, 0.015); - --card-sectionning-background-color: #18232c; - --dropdown-background-color: hsl(205, 30%, 15%); - --dropdown-border-color: #24333e; - --dropdown-box-shadow: var(--card-box-shadow); - --dropdown-color: var(--color); - --dropdown-hover-background-color: rgba(36, 51, 62, 0.75); - --modal-overlay-background-color: rgba(36, 51, 62, 0.8); - --progress-background-color: #24333e; - --progress-color: var(--primary); - --loading-spinner-opacity: 0.5; - --tooltip-background-color: var(--contrast); - --tooltip-color: var(--contrast-inverse); - --icon-checkbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E"); - --icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); - --icon-chevron-button: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); - --icon-chevron-button-inverse: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(0, 0, 0)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); - --icon-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(115, 130, 140)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E"); - --icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E"); - --icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(183, 28, 28)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E"); - --icon-minus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E"); - --icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E"); - --icon-time: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E"); - --icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(46, 125, 50)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E"); - color-scheme: dark; - } -} [data-theme=dark] { --background-color: #11191f; --color: hsl(205, 16%, 77%); |