Translate to Finnish

This commit is contained in:
Saku Laesvuori 2025-10-14 11:27:47 +03:00
parent 6c33f6d821
commit 0098ac874f
20 changed files with 110 additions and 102 deletions

View File

@ -175,6 +175,7 @@ instance Yesod App where
|]
addScript $ StaticR js_bootstrap_min_js
addScript $ StaticR js_bootstrap_datepicker_min_js
addScript $ StaticR js_locales_bootstrap_datepicker_fi_min_js
addScript $ StaticR js_jquery_url_js
addScript $ StaticR js_jquery_cookie_js
addScript $ StaticR js_jquery_hotkeys_js
@ -310,4 +311,7 @@ require :: Permission -> Handler ()
require p = do
VD{perms} <- getViewData
unless (p `elem` perms) $ permissionDenied $
"Missing the '" <> T.pack (showPermission p) <> "' permission"
deniedMessage p <> " (" <> T.pack (showPermission p) <> ")"
where deniedMessage ViewPermission = "Ei oikeutta lukea kirjauksia"
deniedMessage AddPermission = "Ei oikeutta lisätä kirjauksia"
deniedMessage EditPermission = "Ei oikeutta muokata kirjanpitoa"

View File

@ -40,7 +40,7 @@ postAddR = do
liftIO $ do
ensureJournalFileExists f
appendToJournalFileOrStdout f (showTransaction t')
setMessage "Transaction added."
setMessage "Kirjaus lisätty."
redirect JournalR
FormMissing -> showForm view enctype
FormFailure errs -> do
@ -49,7 +49,7 @@ postAddR = do
where
showForm view enctype =
sendResponse =<< defaultLayout [whamlet|
<h2>Add transaction
<h2>Uusi kirjaus
<div .row style="margin-top:1em">
<form#addform.form.col-xs-12.col-sm-11 method=post enctype=#{enctype}>
^{view}

View File

@ -39,13 +39,13 @@ postEditR f = do
newtxt <- fromFormSuccess (showForm view enctype) res
runExceptT (writeJournalTextIfValidAndChanged f newtxt) >>= \case
Left e -> do
setMessage $ "Failed to load journal: " <> toHtml e
setMessage $ "Kirjanpidon lataaminen epäonnistui: " <> toHtml e
showForm view enctype
Right () -> do
setMessage $ "Saved journal " <> toHtml f <> "\n"
setMessage $ "Kirjanpito tallennettu tiedostoon " <> toHtml f <> "\n"
redirect JournalR
where
showForm view enctype =
sendResponse <=< defaultLayout $ do
setTitle "Edit journal"
setTitle "Muokkaa kirjanpitoa"
[whamlet|<form method=post enctype=#{enctype}>^{view}|]

View File

@ -23,9 +23,9 @@ getJournalR = do
VD{perms, j, q, opts, qparam, qopts, today} <- getViewData
require ViewPermission
let title = case inAccount qopts of
Nothing -> "General Journal"
Just (a, inclsubs) -> "Transactions in " <> a <> if inclsubs then "" else " (excluding subaccounts)"
title' = title <> if q /= Any then ", filtered" else ""
Nothing -> "Kaikki kirjaukset"
Just (a, inclsubs) -> "Tapahtumat tilillä " <> a <> if inclsubs then "" else " (poislukien alatilit)"
title' = title <> if q /= Any then ", suodatettu" else ""
acctlink a = (RegisterR, [("q", replaceInacct qparam $ accountQuery a)])
rspec = (reportspec_ $ cliopts_ opts){_rsQuery = filterQuery (not . queryIsDepth) q}
items = reverse $
@ -34,5 +34,5 @@ getJournalR = do
transactionFrag = transactionFragment j
defaultLayout $ do
setTitle "journal - hledger-web"
setTitle "päiväkirja - hledger-web"
$(widgetFile "journal")

View File

@ -44,7 +44,7 @@ getManageR = do
VD{j} <- getViewData
require EditPermission
defaultLayout $ do
setTitle "Edit journal"
setTitle "Muokkaa kirjanpitoa"
$(widgetFile "manage")
getDownloadR :: FilePath -> Handler TypedContent

View File

@ -30,9 +30,9 @@ getRegisterR = do
VD{perms, j, q, opts, qparam, qopts, today} <- getViewData
require ViewPermission
let (a,inclsubs) = fromMaybe ("all accounts",True) $ inAccount qopts
s1 = if inclsubs then "" else " (excluding subaccounts)"
s2 = if q /= Any then ", filtered" else ""
let (a,inclsubs) = fromMaybe ("kaikki tilit",True) $ inAccount qopts
s1 = if inclsubs then "" else " (poislukien alitilit)"
s2 = if q /= Any then ", suodatettu" else ""
header = a <> s1 <> s2
let rspec = reportspec_ (cliopts_ opts)
@ -50,12 +50,12 @@ getRegisterR = do
styleAmounts (journalCommodityStylesWith HardRounding j) $
accountTransactionsReport rspec{_rsQuery=q} j acctQuery
balancelabel
| isJust (inAccount qopts), balanceaccum_ (_rsReportOpts rspec) == Historical = "Historical Total"
| isJust (inAccount qopts) = "Period Total"
| otherwise = "Total"
| isJust (inAccount qopts), balanceaccum_ (_rsReportOpts rspec) == Historical = "Historiallinen saldo"
| isJust (inAccount qopts) = "Kauden saldo"
| otherwise = "Saldo"
transactionFrag = transactionFragment j
defaultLayout $ do
setTitle "register - hledger-web"
setTitle "kirjaukset - hledger-web"
$(widgetFile "register")
-- cf. Hledger.Reports.AccountTransactionsReport.accountTransactionsReportItems

View File

@ -48,20 +48,20 @@ postUploadR f = do
newtxt <- case TE.decodeUtf8' lbs of
Left e -> do
setMessage $
"Encoding error: '" <> toHtml (show e) <> "'. " <>
"If your file is not UTF-8 encoded, try the 'edit form', " <>
"where the transcoding should be handled by the browser."
"Merkistövirhe: '" <> toHtml (show e) <> "'. " <>
"Jos tiedostosi ei käytä UTF-8 merkistöä, kokeile 'muokkaa'-sivua," <>
"jolla selaimesi pitäisi huolehtia merkistön muuntamisesta puolestasi."
showForm view enctype
Right newtxt -> return newtxt
runExceptT (writeJournalTextIfValidAndChanged f newtxt) >>= \case
Left e -> do
setMessage $ "Failed to load journal: " <> toHtml e
setMessage $ "Kirjanpidon lataaminen epäonnistui: " <> toHtml e
showForm view enctype
Right () -> do
setMessage $ "File " <> toHtml f <> " uploaded successfully"
setMessage $ "Tiedoston " <> toHtml f <> " lataaminen onnistui!"
redirect JournalR
where
showForm view enctype =
sendResponse <=< defaultLayout $ do
setTitle "Upload journal"
setTitle "Korvaa tiedosto"
[whamlet|<form method=post enctype=#{enctype}>^{view}|]

View File

@ -96,12 +96,12 @@ hledgerWebTest = do
yit "serves a reasonable-looking journal page" $ do
get JournalR
statusIs 200
bodyContains "Add a transaction"
bodyContains "Uusi kirjaus"
yit "serves a reasonable-looking register page" $ do
get RegisterR
statusIs 200
bodyContains "accounts"
bodyContains "tilit"
yit "hyperlinks use a base url made from the default host and port" $ do
get JournalR

View File

@ -43,7 +43,7 @@ addModal addR j today = do
<div .modal-content>
<div .modal-header>
<button type="button" .close data-dismiss="modal" aria-hidden="true">&times;
<h3 .modal-title #addLabel>Add a transaction
<h3 .modal-title #addLabel>Uusi kirjaus
<div .modal-body>
<form#addform.form action=@{addR} method=POST enctype=#{addEnctype}>
^{addView}
@ -85,8 +85,8 @@ addForm j today = identifyForm "add" $ \extra -> do
| f `elem` fs = Right f
| otherwise = Left $ MsgInputNotFound $ T.pack f
-- field settings
dateSettings = FieldSettings "date" Nothing Nothing (Just "date") [("class", "form-control input-lg"), ("placeholder", "Date")]
descSettings = FieldSettings "desc" Nothing Nothing (Just "description") [("class", "form-control input-lg typeahead"), ("placeholder", "Description"), ("size", "40")]
dateSettings = FieldSettings "date" Nothing Nothing (Just "date") [("class", "form-control input-lg"), ("placeholder", "Päiväys")]
descSettings = FieldSettings "desc" Nothing Nothing (Just "description") [("class", "form-control input-lg typeahead"), ("placeholder", "Selite"), ("size", "40")]
acctSettings = FieldSettings "account" Nothing Nothing (Just "account") []
amtSettings = FieldSettings "amount" Nothing Nothing (Just "amount") []
fileSettings = FieldSettings "file" Nothing Nothing (Just "file") [("class", "form-control input-lg")]

View File

@ -93,6 +93,7 @@ extra-source-files:
static/js/jquery.js
static/js/jquery.min.js
static/js/jquery.url.js
static/js/locales/bootstrap-datepicker.fi.min.js
static/js/typeahead.bundle.js
static/js/typeahead.bundle.min.js
templates/add-form.hamlet

View File

@ -14,6 +14,7 @@ $(document).ready(function() {
autoclose: true,
format: 'yyyy-mm-dd',
todayHighlight: true,
language: 'fi',
weekStart: 1 // Monday
});;
@ -115,8 +116,8 @@ function addformAddPosting() {
// Clear the new account and amount fields and update their placeholder text.
var accountfield = newrow.find('input[name=account]');
var amountfield = newrow.find('input[name=amount]');
accountfield.val('').prop('placeholder', 'Account '+newnum);
amountfield.val('').prop('placeholder', 'Amount '+newnum);
accountfield.val('').prop('placeholder', 'Tili '+newnum);
amountfield.val('').prop('placeholder', 'Summa '+newnum);
// Enable autocomplete in the new account field.
// We must first remove these typehead helper elements cloned from the old row,

View File

@ -0,0 +1 @@
!function(a){a.fn.datepicker.dates.fi={days:["sunnuntai","maanantai","tiistai","keskiviikko","torstai","perjantai","lauantai"],daysShort:["sun","maa","tii","kes","tor","per","lau"],daysMin:["su","ma","ti","ke","to","pe","la"],months:["tammikuu","helmikuu","maaliskuu","huhtikuu","toukokuu","kesäkuu","heinäkuu","elokuu","syyskuu","lokakuu","marraskuu","joulukuu"],monthsShort:["tam","hel","maa","huh","tou","kes","hei","elo","syy","lok","mar","jou"],today:"tänään",clear:"Tyhjennä",weekStart:1,format:"d.m.yyyy"}}(jQuery);

View File

@ -56,23 +56,23 @@
<div .form-group .row .account-group style="padding-left:1em;">
<div .col-sm-9.col-xs-9 :isJust accE:.has-error>
<input .account-input.form-control.input-lg.typeahead type=text
name=account placeholder="Account #{n}" value="#{acc}">
name=account placeholder="Tili #{n}" value="#{acc}">
$maybe err <- accE
<span .help-block .error-block>_{err}
<div .col-sm-3.col-xs-3 :isJust amtE:.has-error>
<input .amount-input.form-control.input-lg type=text
name=amount placeholder="Amount #{n}" value="#{amt}">
name=amount placeholder="Summa #{n}" value="#{amt}">
$maybe err <- amtE
<span .help-block .error-block>_{err}
<div .row>
<div .col-sm-9.col-xs-9>
$if length files > 1
Add to:
Kirjaa tiedostoon:
&nbsp;
<div style="display:inline-block; width:auto;" .form-group :isJust (fvErrors fileView):.has-error>
^{fvInput fileView}
$maybe err <- fvErrors fileView
<span .help-block .error-block>#{err}
<div .col-sm-3.col-xs-3 style="text-align:right;">
<button type=submit .btn .btn-default .btn-lg name=submit style="font-weight:bold;">Save
<button type=submit .btn .btn-default .btn-lg name=submit style="font-weight:bold;">Tallenna

View File

@ -1,8 +1,8 @@
<tr :here == journalR:.inacct>
<td .top .acct>
<a href=@{journalR} :here == journalR:.inacct
title="Show general journal entries, most recent first">
Journal
title="Näytä päiväkirjan kirjaukset uusimmasta vanhimpaan">
Kirjanpito
<td .top>
$forall (acct, adisplay, aindent, abal) <- items
<tr
@ -12,11 +12,12 @@ $forall (acct, adisplay, aindent, abal) <- items
<div .ff-wrapper>
\#{indent aindent}
<a.acct-name href="@?{(registerR, [("q", replaceInacct qparam $ accountQuery acct)])}"
title="Show transactions affecting this account and subaccounts">
title="Näytä tähän tiliin ja sen alitileihin vaikuttavat kirjaukset">
#{adisplay}
$if hasSubAccounts acct
<a href="@?{(registerR, [("q", replaceInacct qparam $ accountOnlyQuery acct)])}" .only.hidden-sm.hidden-xs
title="Show transactions affecting this account but not subaccounts">only
title="Näytä vain juuri tähän tiliin vaikuttavat kirjaukset">only
<td .amount>
^{mixedAmountAsHtml abal}
<tr .total>

View File

@ -17,19 +17,19 @@ $if elem ViewPermission perms
<div #message .alert.alert-info>#{m}
$if elem ViewPermission perms
<form#searchform.input-group method=GET>
<input .form-control name=q value=#{qparam} placeholder="Search"
title="Enter hledger search patterns to filter the data below">
<input .form-control name=q value=#{qparam} placeholder="Hae"
title="Syötä hakuehtoja rajataksesi alla olevaa dataa">
<div .input-group-btn>
$if not (T.null qparam)
<a href=@{here} .btn .btn-default title="Clear search terms">
<a href=@{here} .btn .btn-default title="Tyhjennä hakuehdot">
<span .glyphicon .glyphicon-remove-circle>
<button .btn .btn-default type=submit title="Apply search terms">
<button .btn .btn-default type=submit title="Hae">
<span .glyphicon .glyphicon-search>
$if elem EditPermission perms
<a href="@{ManageR}" .btn.btn-default title="Manage journal files">
<a href="@{ManageR}" .btn.btn-default title="Hallinnoi kirjanpidon tiedostoja">
<span .glyphicon .glyphicon-wrench>
<button .btn .btn-default type=button data-toggle="modal" data-target="#helpmodal"
title="Show search and general help">
title="Näytä käyttöohjeita">
<span .glyphicon .glyphicon-question-sign>
^{widget}
@ -44,43 +44,43 @@ $if elem ViewPermission perms
<div .row>
<div .col-xs-6>
<p>
<b>Keyboard shortcuts
<b>Pikanäppäimet
<ul>
<li> <code>h</code> or maybe <code>?</code> - view this help (escape or click to exit)
<li> <code>j</code> - go to the Journal view (home)
<li> <code>a</code> - add a transaction (escape to cancel)
<li> <code>s</code> - toggle sidebar
<li> <code>f</code> - focus search form ("find")
<li> <code>e</code> - hide empty accounts in sidebar
<li> <code>h</code> tai (selaimesta riippuen) myös <code>?</code> - näytä nämä ohjeet (paina <code>esc</code> tai klikkaa ruksia poistuaksesi)
<li> <code>j</code> - siirry päiväkirjanäkymään (etusivulle)
<li> <code>a</code> - lisää uusi kirjaus (paina <code>esc</code> peruaksesi)
<li> <code>s</code> - vaihda sivupalkki näkyviin/piilotetuksi
<li> <code>f</code> - kohdista hakukenttään
<li> <code>e</code> - piilota nollasaldoiset tilit sivupalkista
<p>
<b>General
<b>Yleistä
<ul>
<li> The Journal view shows general journal entries, representing zero-sum movements of money (or other commodity) between hierarchical accounts
<li> The sidebar shows the resulting accounts and their final balances
<li> Parent account balances include subaccount balances
<li> Multiple currencies in balances are displayed one above the other
<li> Click account name links to see transactions affecting that account, with running balance
<li> Click date links to see journal entries on that date
<li> Pääkirja näytää kirjauksia, jotka esittävät rahan (tai muun hyödykkeen) täydellisiä siirtoja tilien välillä. Siirron täydellisyydellä tarkoitetaan sitä, ettei siitä ole jätetty mitään osaa kirjaamatta, jolloin hyödykettä ei katoa eikä synny tyhjästä.
<li> Sivupalkki näyttää käytetyt tilit ja niiden loppusaldot
<li> Ylätilien saldot sisältävät niiden alatilien saldot
<li> Eri valuutat esitetään saldoissa päällekkäin
<li> Klikkaamalla tilin nimeä näet siihen vaikuttavat kirjaukset ja saldon joka siirron jälkeen
<li> Klikkaamalla päiväystä näet silloin kirjatut tapahtumat
<div .col-xs-6>
<p>
<b>Search
<b>Haku
<ul>
<li> Search patterns with spaces should be enclosed in quotes.
<li> <code>REGEX</code> - match account names
<li> <code>type:TYPE</code> - match account types
<li> <code>date:PERIODEXP</code> - match dates
<li> <code>status:*</code>, <code>status:!</code>, <code>status:</code> - match status
<li> <code>code:REGEX</code> - match transaction codes
<li> <code>desc:REGEX</code> - match transaction descriptions
<li> <code>payee:REGEX</code> - match payee part of descriptions
<li> <code>note:REGEX</code> - match note part of descriptions
<li> <code>amt:N</code>, <code>amt:&lt;N</code>, <code>amt:&gt;N</code> - match unsigned magnitudes, or with signed N, signed amounts. For single-commodity amounts only.
<li> <code>cur:REGEX</code> - match currencies/commodities. Must match the whole symbol/name. To match dollar sign, write <code>\$</code>
<li> <code>tag:NAME</code>, <code>tag:NAME=REGEX</code> - match tags, or tag and value
<li> <code>real:BOOL</code> - match postings' realness/virtualness
<li> <code>not:QTERM</code> - prepend not: to negate a search term
<li> <code>expr:'QEXPR'</code> - match with a boolean query (and, or, not, (..))
<li> <code>any:'QEXPR'</code> - match transactions where any posting matches
<li> <code>all:'QEXPR'</code> - match transactions where all postings match
<li style="margin-top:1em;"> <code>depth:N</code> - clip account names at this depth
$# <li> Description, account, status query terms are OR'ed, others are AND'ed.
<li> Hakuehdot erotellaan välilyönneillä. Välilyönnin voi sisällyttää hakuehtoon ympäröimällä ehdon yksin- tai kaksinkertaisilla suorilla lainausmerkeillä (<code>"</code> tai <code>'</code>)
<li> <code>REGEX</code> - suodata tilin nimellä
<li> <code>type:TYPE</code> - suoda tilin tyypillä (X kuluille, R tuotoille, A vastaaville, E omalle pääomalle ja L vieraalle pääomalle)
<li> <code>date:PERIODEXP</code> - suodata päiväyksen perusteella.
<li> <code>status:*</code>, <code>status:!</code>, <code>status:</code> - suodata kirjauksen tilan perusteella (valmis, kesken, tarkistamaton)
<li> <code>code:REGEX</code> - suodata kirjauksen numerolla (esim. tilisiirron viitenumero)
<li> <code>desc:REGEX</code> - suodata selitteellä
<li> <code>payee:REGEX</code> - suodata maksajan/saajan nimellä
<li> <code>note:REGEX</code> - suodata selitteen muulla osalla kuin maksajan/saajan nimellä
<li> <code>amt:N</code>, <code>amt:&lt;N</code>, <code>amt:&gt;N</code> - suodata summan (itseisarvon) suuruuden perusteella. Etumerkin + tai &minus; lisääminen luvun <code>N</code> eteen rajoittaa suodatuksen vain sen merkkisiin summiin. (ei yhdistä eri valuuttojen määriä)
<li> <code>cur:REGEX</code> - suodata valuutan/hyödykkeen tunnuksella. (koko tunnuksen täytyy täsmätä)
<li> <code>tag:NIMI</code>, <code>tag:NIMI=REGEX</code> - suodata tunnisteen nimellä tai nimellä ja arvolla
<li> <code>real:BOOL</code> - suodata siirtojen todellisuuden/näennäisyyden perusteella. Näennäissiirtojen summa ei välttämättä ole nolla, eli ne voivat hävittää kirjanpidosta rahaa tai tuoda sitä sinne tyhjästä.
<li> <code>not:QTERM</code> - Lisää ehdon alkuun <code>not:</code> valitaksesi ne tapahtumat, jotka eivät toteuta ehtoa
<li> <code>expr:'QEXPR'</code> - suodata loogisella lauseella. Tällöin hakuehtoja voi yhdistää vaatimaan molempia (and) tai jompaa kumpaa (or) toteutumaan tai olemaan toteutumatta (not). Ryhmittelyyn voi käyttää kaarisulkuja.
<li> <code>any:'QEXPR'</code> - suodata tapahtumat, joiden jokin siirto toteuttaa hakuehdon
<li> <code>all:'QEXPR'</code> - suodata tapahtumat, joiden jokainen siirto toteuttaa hakuehdon
<li style="margin-top:1em;"> <code>depth:N</code> - rajoita niihin tileihin, joilla on alle <code>N</code> ylätiliä
$# <li> Selitteen, tilin nimen ja kirjauksen tilan hakuehdoista riittää toteuttaa yksi, muista ehdoista tapahtuman pitää toteuttaa kaikki tullakseen valituksi.

View File

@ -1,9 +1,9 @@
#{extra}
<h2>
Edit file #
Muokkaa tiedostoa #
<i>#{f}
<div.alert.alert-danger>
Are you sure? This will overwrite your journal!
Oletko varma? Tämä korvaa vanhan tiedoston täysin!
<table.table.table-condensed>
<tr>
<td colspan=2 style="border:0">
@ -11,7 +11,7 @@
<tr>
<td style="border:0">
<span.help>
^{helplink "data-formats" "File format help"}
^{helplink "data-formats" "Apua tiedostomudon kanssa (englanniksi)"}
<td .text-right style="border:0">
<a.btn.btn-default href="@{ManageR}">Go back
<input.btn.btn-default type=submit value="Save">
<a.btn.btn-default href="@{ManageR}">Peruuta
<input.btn.btn-default type=submit value="Tallenna">

View File

@ -3,16 +3,16 @@
$if elem AddPermission perms
<a #addformlink href="#" role="button" style="cursor:pointer; margin-top:1em;"
data-toggle="modal" data-target="#addmodal" title="Add a new transaction to the journal">
Add a transaction
data-toggle="modal" data-target="#addmodal" title="Lisää uusi tapahtuma kirjanpitoon.">
Kirjaa tapahtuma
<div .table-responsive>
<table .transactionsreport .table .table-condensed>
<thead>
<th .date style="text-align:left;">Date
<th .description style="text-align:left;">Description
<th .account style="text-align:left;">Account
<th .amount style="text-align:right;">Amount
<th .date style="text-align:left;">Päiväys
<th .description style="text-align:left;">Selite
<th .account style="text-align:left;">Tili
<th .amount style="text-align:right;">Summa
$forall torig <- items
<tr .title ##{transactionFrag torig} title="#{showTransaction torig}">

View File

@ -1,12 +1,12 @@
<h2>
Your journal's files
Kirjanpitosi tiedostot
<div.row>
<div .col-md-6.col-sm-8.col-xs-12>
<table .table.table-condensed>
<thead>
<th>
File
Tiedosto
<th>
<tbody>
$forall (path, _) <- jfiles j
@ -15,8 +15,8 @@
#{path}
<td style="text-align:right">
<a.btn.btn-default href=@{EditR path}>
Edit
Muokkaa
<a.btn.btn-default href=@{UploadR path}>
Upload
Korvaa uudella
<a.btn.btn-default href=@{DownloadR path}>
Download
Imuroi

View File

@ -9,11 +9,11 @@
<thead>
<tr>
<th style="text-align:left;">
Date
Päiväys
<span .glyphicon.glyphicon-chevron-up>
<th style="text-align:left;">Description
<th style="text-align:left;">To/From Account(s)
<th style="text-align:right; white-space:normal;">Amount Out/In
<th style="text-align:left;">Kuvaus
<th style="text-align:left;">Tileille/Tileiltä
<th style="text-align:right; white-space:normal;">Siirretty summa
<th style="text-align:right; white-space:normal;">
#{balancelabel}

View File

@ -1,14 +1,14 @@
<h2>
Upload to file #
Korvaa tiedosto #
<i>#{f}
<div.alert.alert-danger>
Are you sure? This will overwrite your journal!
Oletko varma? Tämä korvaa vanhan tiedoston täysin!
<div.form-group>
<label .btn.btn-primary for="file">
<input type=file id=file name=file style="display:none"
onchange="\$('#file-info').html(this.files[0].name)" />
Select file
Valitse korvattava tiedosto
<span .label.label-info id="file-info">
<div.form-group>
<input .btn.btn-default type=submit value="Upload">
<input .btn.btn-default type=submit value="Korvaa">
#{extra}