diff --git a/cfg/config.go b/cfg/config.go index fbe0107..d47ca38 100644 --- a/cfg/config.go +++ b/cfg/config.go @@ -6,6 +6,8 @@ import ( "log" "os" "path/filepath" + + "github.com/bouncepaw/mycorrhiza/plugin/lang" ) type MyceliumConfig struct { @@ -23,20 +25,18 @@ const ( ) var ( - DescribeHyphaHerePattern = "Describe %s here" - WikiDir string - configJsonPath string + Locale map[string]string + WikiDir string + configJsonPath string // Default values that can be overriden in config.json - Address = "0.0.0.0:80" - TitleEditTemplate = `Edit %s` - TitleTemplate = `%s` - GenericErrorMsg = `Sorry, something went wrong` - SiteTitle = `MycorrhizaWiki` - Theme = `default-light` - HomePage = `/Home` - BinaryLimit int64 = 10 << 20 - Mycelia = []MyceliumConfig{ + Address = "0.0.0.0:80" + LocaleName = "en" + SiteTitle = `MycorrhizaWiki` + Theme = `default-light` + HomePage = `/Home` + BinaryLimit int64 = 10 << 20 + Mycelia = []MyceliumConfig{ {[]string{"main"}, "main"}, {[]string{"sys", "system"}, "system"}, } @@ -63,16 +63,13 @@ func readConfig() bool { } cfg := struct { - Address string `json:"address"` - Theme string `json:"theme"` - SiteTitle string `json:"site-title"` - HomePage string `json:"home-page"` - BinaryLimitMB int64 `json:"binary-limit-mb"` - Mycelia []MyceliumConfig `json:"mycelia"` - TitleTemplates struct { - EditHypha string `json:"edit-hypha"` - ViewHypha string `json:"view-hypha"` - } `json:"title-templates"` + Address string `json:"address"` + Theme string `json:"theme"` + SiteTitle string `json:"site-title"` + HomePage string `json:"home-page"` + BinaryLimitMB int64 `json:"binary-limit-mb"` + LocaleName string `json:"locale"` + Mycelia []MyceliumConfig `json:"mycelia"` }{} err = json.Unmarshal(configJsonContents, &cfg) @@ -84,11 +81,16 @@ func readConfig() bool { Address = cfg.Address Theme = cfg.Theme SiteTitle = cfg.SiteTitle - TitleEditTemplate = cfg.TitleTemplates.EditHypha - TitleTemplate = cfg.TitleTemplates.ViewHypha HomePage = "/" + cfg.HomePage BinaryLimit = 1024 * cfg.BinaryLimitMB Mycelia = cfg.Mycelia + switch cfg.LocaleName { + case "en": + Locale = lang.EnglishMap + default: + Locale = lang.EnglishMap + } + return true } diff --git a/fs/data.go b/fs/data.go index 58b7264..15599cf 100644 --- a/fs/data.go +++ b/fs/data.go @@ -82,5 +82,5 @@ func (h *Hypha) TextContent() string { } return string(contents) } - return fmt.Sprintf(cfg.DescribeHyphaHerePattern, h.FullName) + return fmt.Sprintf(cfg.Locale["edit/box/help pattern"], h.FullName) } diff --git a/main.go b/main.go index dbd2fe1..d2eb2b1 100644 --- a/main.go +++ b/main.go @@ -60,7 +60,7 @@ func main() { r := mux.NewRouter() r.HandleFunc("/favicon.ico", func(w http.ResponseWriter, rq *http.Request) { - http.ServeFile(w, rq, filepath.Join(filepath.Dir(cfg.WikiDir), "favicon.ico")) + http.ServeFile(w, rq, filepath.Join(cfg.WikiDir, "favicon.ico")) }) IdempotentRouterBoiler(r, "binary", HandlerBinary) diff --git a/plugin/lang/en.go b/plugin/lang/en.go new file mode 100644 index 0000000..049c38b --- /dev/null +++ b/plugin/lang/en.go @@ -0,0 +1,31 @@ +package lang + +var EnglishMap = map[string]string{ + "edit hypha title template": "Edit %s at MycorrhizaWiki", + "view hypha title template": "%s at MycorrhizaWiki", + "this site runs myco wiki": `
This website runs MycorrhizaWiki
`, + "generic error msg": `Sorry, something went wrong`, + + "edit/text mime type": "Text MIME-type", + "edit/text mime type/tip": "We supporttext/markdown
, text/creole
and text/gemini
",
+
+ "edit/revision comment": "Revision comment",
+ "edit/revision comment/tip": "Please make your comment helpful",
+ "edit/revision comment/new": "Create %s",
+ "edit/revision comment/old": "Update %s",
+
+ "edit/tags": "Edit tags",
+ "edit/tags/tip": "Tags are separated by commas, whitespace is ignored",
+
+ "edit/upload file": "Upload file",
+ "edit/upload file/tip": "Only images are fully supported for now",
+
+ "edit/box": "Edit box",
+ "edit/box/title": "Edit %s",
+ "edit/box/help pattern": "Describe %s here",
+
+ "edit/cancel": "Cancel",
+
+ "update ok/title": "Saved %s",
+ "update ok/msg": "Saved successfully. Go back",
+}
diff --git a/render/render.go b/render/render.go
index 095dff5..6ac8a58 100644
--- a/render/render.go
+++ b/render/render.go
@@ -11,59 +11,59 @@ import (
"github.com/bouncepaw/mycorrhiza/mycelium"
)
+func titleTemplateView(name string) string {
+ return fmt.Sprintf(cfg.Locale["view hypha title template"], name)
+}
+
// HyphaEdit renders hypha editor.
func HyphaEdit(h *fs.Hypha) []byte { //
- hyphaData := map[string]string{
+ hyphaData := map[string]interface{}{
"Name": h.FullName,
"Tags": h.TagsJoined(),
"TextMime": h.TextMime(),
"Text": h.TextContent(),
+ "Locale": cfg.Locale,
}
return layout("edit/index").
withMap(hyphaData).
wrapInBase(map[string]string{
- "Title": fmt.Sprintf(cfg.TitleEditTemplate, h.FullName),
+ "Title": fmt.Sprintf(cfg.Locale["edit hypha title template"], h.FullName),
})
}
// HyphaUpdateOk is used to inform that update was successful.
func HyphaUpdateOk(h *fs.Hypha) []byte { //
return layout("update_ok").
- withMap(map[string]string{"Name": h.FullName}).
+ withMap(map[string]interface{}{
+ "Name": h.FullName,
+ "Locale": cfg.Locale,
+ }).
Bytes()
}
// Hypha404 renders 404 page for nonexistent page.
func Hypha404(name, _ string) []byte {
return layout("view/404").
- withMap(map[string]string{
+ withMap(map[string]interface{}{
"PageTitle": name,
"Tree": hyphaTree(name),
+ "Locale": cfg.Locale,
}).
wrapInBase(map[string]string{
- "Title": fmt.Sprintf(cfg.TitleTemplate, name),
+ "Title": titleTemplateView(name),
})
}
// HyphaPage renders hypha viewer.
func HyphaPage(name, content string) []byte {
return layout("view/index").
- withMap(map[string]string{
+ withMap(map[string]interface{}{
"Content": content,
"Tree": hyphaTree(name),
+ "Locale": cfg.Locale,
}).
wrapInBase(map[string]string{
- "Title": fmt.Sprintf(cfg.TitleTemplate, name),
- })
-}
-
-// hyphaGeneric is used when building renderers for all types of hypha pages
-func hyphaGeneric(name, content, templateName string) []byte {
- return layout(templateName).
- withString(content).
- wrapInBase(map[string]string{
- "Title": fmt.Sprintf(cfg.TitleTemplate, name),
- "Sidebar": hyphaTree(name),
+ "Title": titleTemplateView(name),
})
}
@@ -72,9 +72,10 @@ func (lyt *Layout) wrapInBase(keys map[string]string) []byte {
if lyt.invalid {
return lyt.Bytes()
}
- page := map[string]string{
- "Title": cfg.SiteTitle,
+ page := map[string]interface{}{
"Content": lyt.String(),
+ "Locale": cfg.Locale,
+ "Title": cfg.SiteTitle,
"SiteTitle": cfg.SiteTitle,
}
for key, val := range keys {
@@ -122,7 +123,7 @@ func (lyt *Layout) withString(data string) *Layout {
return lyt
}
-func (lyt *Layout) withMap(data map[string]string) *Layout {
+func (lyt *Layout) withMap(data map[string]interface{}) *Layout {
if lyt.invalid {
return lyt
}
diff --git a/wiki/config.json b/wiki/config.json
index 3d41bce..67c2da8 100644
--- a/wiki/config.json
+++ b/wiki/config.json
@@ -4,10 +4,7 @@
"site-title": "🍄 MycorrhizaWiki",
"home-page": "Home",
"binary-limit-mb": 10,
- "title-templates": {
- "edit-hypha": "Edit %s at MycorrhizaWiki",
- "view-hypha": "%s at MycorrhizaWiki"
- },
+ "locale": "en",
"mycelia": [
{
"names": ["main"],
diff --git a/wiki/main/doc/plugin/3.markdown b/wiki/main/doc/plugin/3.markdown
new file mode 100644
index 0000000..702f628
--- /dev/null
+++ b/wiki/main/doc/plugin/3.markdown
@@ -0,0 +1,27 @@
+# Plugin system RFC
+MycorrhizaWiki engine does not provide all the functionality a wiki may need and not need. Instead, it relies on the system of plugins.
+
+This document is up-to-date.
+
+## Types of plugins
+- **Parser.** They add support for displaying different MIME-types.
+- **Language.** They provide i18n support.
+
+## Default plugins
+Default MycorrhizaWiki distributive is shipped with several plugins installed.
+
+- **parser/markdown.** Support for `text/markdown`. This parser is powered by [russross/blackfriday](https://github.com/russross/blackfriday); this parser is ok, I guess.
+- **parser/creole.** Support for `text/creole`. *Note:* there is no standard Creole MIME type. This parser is powered by [m4tty/cajun](https://github.com/m4tty/cajun); this library is somewhat outdated. Perhaps we'll reimplement it.
+- **parser/gemini.** Support for `text/gemini`.
+- **language/en.** Support for English language.
+
+## Plugin implementation
+All plugins are written in Go and are compiled together with MycorrhizaWiki. If a wiki's admin decides to add a plugin, they shall recompile the engine with the plugin.
+
+> Reminds of [something](http://suckless.org/), right?
+
+*But compiling the engine just to add a plugin is stupid!!* Not really. Also, it makes the architecture more simple and secure.
+
+*What if an admin doesn't know how to program?* Plugin installation is basically limited to putting some files into a folder, editing the config and running a shell command. No programming required to install a plugin.
+
+See `plugin` directory at the root of the repo to get inspired by the present parsers.
diff --git a/wiki/main/doc/plugin/4.markdown b/wiki/main/doc/plugin/4.markdown
new file mode 100644
index 0000000..961a49b
--- /dev/null
+++ b/wiki/main/doc/plugin/4.markdown
@@ -0,0 +1,27 @@
+# Plugin system RFC
+MycorrhizaWiki engine does not provide all the functionality a wiki may need and not need. Instead, it relies on the system of plugins.
+
+This document is up-to-date.
+
+## Types of plugins
+- **Parser.** They add support for displaying different MIME-types.
+- **Language.** They provide i18n support.
+
+## Default plugins
+Default MycorrhizaWiki distributive is shipped with several plugins installed.
+
+- **parser/markdown.** Support for `text/markdown`. This parser is powered by [russross/blackfriday](https://github.com/russross/blackfriday); this parser is ok, I guess.
+- **parser/creole.** Support for `text/creole`. *Note:* there is no standard Creole MIME type. This parser is powered by [m4tty/cajun](https://github.com/m4tty/cajun); this library is somewhat outdated. Perhaps we'll reimplement it.
+- **parser/gemini.** Support for `text/gemini`.
+- **lang/en.** Support for English language.
+
+## Plugin implementation
+All plugins are written in Go and are compiled together with MycorrhizaWiki. If a wiki's admin decides to add a plugin, they shall recompile the engine with the plugin.
+
+> Reminds of [something](http://suckless.org/), right?
+
+*But compiling the engine just to add a plugin is stupid!!* Not really. Also, it makes the architecture more simple and secure.
+
+*What if an admin doesn't know how to program?* Plugin installation is basically limited to putting some files into a folder, editing the config and running a shell command. No programming required to install a plugin.
+
+See `plugin` directory at the root of the repo to get inspired by the present parsers.
diff --git a/wiki/main/doc/plugin/5.markdown b/wiki/main/doc/plugin/5.markdown
new file mode 100644
index 0000000..44b04e4
--- /dev/null
+++ b/wiki/main/doc/plugin/5.markdown
@@ -0,0 +1,32 @@
+# Plugin system RFC
+MycorrhizaWiki engine does not provide all the functionality a wiki may need and not need. Instead, it relies on the system of plugins.
+
+This document is up-to-date.
+
+## Types of plugins
+- **Parser.** They add support for displaying different MIME-types.
+- **Language.** They provide i18n support.
+
+## Default plugins
+Default MycorrhizaWiki distributive is shipped with several plugins installed.
+
+- **parser/markdown.** Support for `text/markdown`. This parser is powered by [russross/blackfriday](https://github.com/russross/blackfriday); this parser is ok, I guess.
+- **parser/creole.** Support for `text/creole`. *Note:* there is no standard Creole MIME type. This parser is powered by [m4tty/cajun](https://github.com/m4tty/cajun); this library is somewhat outdated. Perhaps we'll reimplement it.
+- **parser/gemini.** Support for `text/gemini`.
+- **lang/en.** Support for English language.
+
+## Plugin implementation
+All plugins are written in Go and are compiled together with MycorrhizaWiki. If a wiki's admin decides to add a plugin, they shall recompile the engine with the plugin.
+
+> Reminds of [something](http://suckless.org/), right?
+
+*But compiling the engine just to add a plugin is stupid!!* Not really. Also, it makes the architecture more simple and secure.
+
+*What if an admin doesn't know how to program?* Plugin installation is basically limited to putting some files into a folder, editing the config and running a shell command. No programming required to install a plugin.
+
+See `plugin` directory at the root of the repo to get inspired by the present parsers.
+
+## Possible future plugins
+- **Utilites.** Plugins that can do different things and provide their own hypha interface in `:spec` mycelium.
+- **Macros.** Dynamic content parts that are generated when page is accessed: TOC, meta information accessors, etc.
+
diff --git a/wiki/main/doc/plugin/6.markdown b/wiki/main/doc/plugin/6.markdown
new file mode 100644
index 0000000..44b04e4
--- /dev/null
+++ b/wiki/main/doc/plugin/6.markdown
@@ -0,0 +1,32 @@
+# Plugin system RFC
+MycorrhizaWiki engine does not provide all the functionality a wiki may need and not need. Instead, it relies on the system of plugins.
+
+This document is up-to-date.
+
+## Types of plugins
+- **Parser.** They add support for displaying different MIME-types.
+- **Language.** They provide i18n support.
+
+## Default plugins
+Default MycorrhizaWiki distributive is shipped with several plugins installed.
+
+- **parser/markdown.** Support for `text/markdown`. This parser is powered by [russross/blackfriday](https://github.com/russross/blackfriday); this parser is ok, I guess.
+- **parser/creole.** Support for `text/creole`. *Note:* there is no standard Creole MIME type. This parser is powered by [m4tty/cajun](https://github.com/m4tty/cajun); this library is somewhat outdated. Perhaps we'll reimplement it.
+- **parser/gemini.** Support for `text/gemini`.
+- **lang/en.** Support for English language.
+
+## Plugin implementation
+All plugins are written in Go and are compiled together with MycorrhizaWiki. If a wiki's admin decides to add a plugin, they shall recompile the engine with the plugin.
+
+> Reminds of [something](http://suckless.org/), right?
+
+*But compiling the engine just to add a plugin is stupid!!* Not really. Also, it makes the architecture more simple and secure.
+
+*What if an admin doesn't know how to program?* Plugin installation is basically limited to putting some files into a folder, editing the config and running a shell command. No programming required to install a plugin.
+
+See `plugin` directory at the root of the repo to get inspired by the present parsers.
+
+## Possible future plugins
+- **Utilites.** Plugins that can do different things and provide their own hypha interface in `:spec` mycelium.
+- **Macros.** Dynamic content parts that are generated when page is accessed: TOC, meta information accessors, etc.
+
diff --git a/wiki/main/doc/plugin/meta.json b/wiki/main/doc/plugin/meta.json
index e2f04b5..ccfb082 100644
--- a/wiki/main/doc/plugin/meta.json
+++ b/wiki/main/doc/plugin/meta.json
@@ -27,6 +27,58 @@
"binary_mime": "",
"text_name": "2.markdown",
"binary_name": ""
+ },
+ "3": {
+ "tags": [
+ ""
+ ],
+ "name": "Plugin",
+ "comment": "Update :Main/Doc/Plugin",
+ "author": "",
+ "time": 1594999571,
+ "text_mime": "text/markdown",
+ "binary_mime": "",
+ "text_name": "3.markdown",
+ "binary_name": ""
+ },
+ "4": {
+ "tags": [
+ ""
+ ],
+ "name": "Plugin",
+ "comment": "Update :Main/Doc/Plugin",
+ "author": "",
+ "time": 1595001530,
+ "text_mime": "text/markdown",
+ "binary_mime": "",
+ "text_name": "4.markdown",
+ "binary_name": ""
+ },
+ "5": {
+ "tags": [
+ ""
+ ],
+ "name": "Plugin",
+ "comment": "Update :Main/Doc/Plugin",
+ "author": "",
+ "time": 1595092102,
+ "text_mime": "text/markdown",
+ "binary_mime": "",
+ "text_name": "5.markdown",
+ "binary_name": ""
+ },
+ "6": {
+ "tags": [
+ ""
+ ],
+ "name": "Plugin",
+ "comment": "Update :Main/Doc/Plugin",
+ "author": "",
+ "time": 1595092219,
+ "text_mime": "text/markdown",
+ "binary_mime": "",
+ "text_name": "6.markdown",
+ "binary_name": ""
}
}
}
\ No newline at end of file
diff --git a/wiki/main/doc/user/1.txt b/wiki/main/doc/user/1.txt
new file mode 100644
index 0000000..472bd33
--- /dev/null
+++ b/wiki/main/doc/user/1.txt
@@ -0,0 +1,7 @@
+Unlike earliest wiki engines, MycorrhizaWiki supports authorization system and non-authorized edits are disabled by default. Anyone can get an account on a MycorrhizaWiki wiki by signing up. There must be a form for that.
+
+* Each user is part of one or more user groups.
+* Each user has a username. Usernames follow the same naming conventions as hyphae but additionally the forward slash / character is prohibited in usernames. Please note that usernames are case-insensitive, thus //shroom// and //Shroom// mean the same; spaces and underscores are also the same, //amanita muscaria// = //amanita_muscaria//.
+* Password chosen by the user is not directly stored on the server. Only its hash is salted so even if a server is hacked, a hacker won't get the passwords. There are no restrictions on passwords. Server administrator doesn't have access to the password as well.
+* Each user gets their own hypha in the //:user// mycelium. The hypha has the same name as the user. Subhyphae can also be added.
+* If an authenticated user makes an edit, the fact that they have made the edit is stored in the revision history.
diff --git a/wiki/main/doc/user/2.txt b/wiki/main/doc/user/2.txt
new file mode 100644
index 0000000..98c4781
--- /dev/null
+++ b/wiki/main/doc/user/2.txt
@@ -0,0 +1,9 @@
+This document is not up-to-date. Information here will be true once we finish its development :)
+
+Unlike earliest wiki engines, MycorrhizaWiki supports authorization system and non-authorized edits are disabled by default. Anyone can get an account on a MycorrhizaWiki wiki by signing up. There must be a form for that.
+
+* Each user is part of one or more user groups.
+* Each user has a username. Usernames follow the same naming conventions as hyphae but additionally the forward slash / character is prohibited in usernames. Please note that usernames are case-insensitive, thus //shroom// and //Shroom// mean the same; spaces and underscores are also the same, //amanita muscaria// = //amanita_muscaria//.
+* Password chosen by the user is not directly stored on the server. Only its hash is salted so even if a server is hacked, a hacker won't get the passwords. There are no restrictions on passwords. Server administrator doesn't have access to the password as well.
+* Each user gets their own hypha in the //:user// mycelium. The hypha has the same name as the user. Subhyphae can also be added.
+* If an authenticated user makes an edit, the fact that they have made the edit is stored in the revision history.
diff --git a/wiki/main/doc/user/meta.json b/wiki/main/doc/user/meta.json
new file mode 100644
index 0000000..0ee761d
--- /dev/null
+++ b/wiki/main/doc/user/meta.json
@@ -0,0 +1,32 @@
+{
+ "views": 0,
+ "deleted": false,
+ "revisions": {
+ "1": {
+ "tags": [
+ ""
+ ],
+ "name": "User",
+ "comment": "Update :Main/Doc/User",
+ "author": "",
+ "time": 1594749111,
+ "text_mime": "text/creole",
+ "binary_mime": "",
+ "text_name": "1.txt",
+ "binary_name": ""
+ },
+ "2": {
+ "tags": [
+ ""
+ ],
+ "name": "User",
+ "comment": "Update :Main/Doc/User",
+ "author": "",
+ "time": 1595092543,
+ "text_mime": "text/creole",
+ "binary_mime": "",
+ "text_name": "2.txt",
+ "binary_name": ""
+ }
+ }
+}
\ No newline at end of file
diff --git a/wiki/main/doc/wikilink/3.markdown b/wiki/main/doc/wikilink/3.markdown
new file mode 100644
index 0000000..28598d7
--- /dev/null
+++ b/wiki/main/doc/wikilink/3.markdown
@@ -0,0 +1,51 @@
+# Wikilink RFC
+
+*This page is not up-to-date. One day, features defined here shall be implemented.*
+
+All parsers for MycorrhizaWiki provide hyperlink support. Usually, they follow HTML convention.
+
+- `http://example.org/absolute-path`
+- `/rooted-path`
+- `same-folder-path`
+- `../parent-folder-path`
+
+This is not really convenient for wikis where most of links are either rooted or links to children!
+
+All parsers of MycorrhizaWiki are expected to support these types of links and convert them to rooted paths.
+
+- `http://example.org/absolute-path`
+- `hypha in main mycelium`
+- `::hypha in the same mycelium`
+- `:mycelium/hypha in an explicit mycelium`
+- `/subhypha`
+- `./subhypha`
+- `../sibling-hypha`
+
+**TODO:** create a package that implements this thing. NB: to generate a correct link, it is required to know full name of hypha where the link is used.
+
+## Markdown extension
+
+> This is an extension to markdown's syntax that is used in MycorrhizaWiki and nowhere else.
+
+Text wrapped in `[[` and `]]` is a link that has same text and url. *For some reason it's not possible in Markdown without duplicating url*
+
+```
+[[x]] == [x](x)
+```
+
+## Examples
+
+All examples assume that `:example/test` is the current hypha.
+
+```
+wikilink actual path
+foo == /foo
+::foo == /:example/foo
+:bar/foo == /:bar/foo
+/baz == /:example/test/baz
+./baz == /:example/test/baz
+../qux == /:example/qux
+http://example.org == http://example.org
+gemini://example.org == gemini://example.org
+mailto:me@example.org == mailto:me@example.org
+```
diff --git a/wiki/main/doc/wikilink/meta.json b/wiki/main/doc/wikilink/meta.json
index 7b2f55e..09c4ea1 100644
--- a/wiki/main/doc/wikilink/meta.json
+++ b/wiki/main/doc/wikilink/meta.json
@@ -27,6 +27,19 @@
"binary_mime": "",
"text_name": "2.markdown",
"binary_name": ""
+ },
+ "3": {
+ "tags": [
+ ""
+ ],
+ "name": "Wikilink",
+ "comment": "Update :Main/Doc/Wikilink",
+ "author": "",
+ "time": 1595092265,
+ "text_mime": "text/markdown",
+ "binary_mime": "",
+ "text_name": "3.markdown",
+ "binary_name": ""
}
}
}
\ No newline at end of file
diff --git a/wiki/sys/theme/default-light/base.html/1.html b/wiki/sys/theme/default-light/base.html/1.html
index 07d5cbf..511eed0 100644
--- a/wiki/sys/theme/default-light/base.html/1.html
+++ b/wiki/sys/theme/default-light/base.html/1.html
@@ -17,7 +17,7 @@
{{ .Content }}
- Saved successfully. Go back
+{{printf (index .Locale "update ok/msg") .Name}}
diff --git a/wiki/sys/theme/default-light/edit/index.html/1.html b/wiki/sys/theme/default-light/edit/index.html/1.html
index 080e1a5..db331e8 100644
--- a/wiki/sys/theme/default-light/edit/index.html/1.html
+++ b/wiki/sys/theme/default-light/edit/index.html/1.html
@@ -5,38 +5,39 @@
id="edit-form">
Edit {{ .Name }}
+ {{printf (index .Locale "edit/box/title") .Name}}
-
+