diff --git a/Dockerfile b/Dockerfile
index 9e012712d..bf67cba99 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -54,7 +54,7 @@ COPY ./ /src
WORKDIR /src
# Take note of SILE's supported locales so the final system can build localized messages
-RUN ls i18n/ | sed 's/[.-].*$/_/;s/^/^/' | sort -u | grep -Ef - /usr/share/i18n/SUPPORTED > /etc/locale.gen
+RUN ls -d languages/*/ | sed -e 's!/$!_!;s!.*/!^!' | sort -u | grep -Ef - /usr/share/i18n/SUPPORTED > /etc/locale.gen
# GitHub Actions builder stopped providing git history :(
# See feature request at https://github.com/actions/runner/issues/767
diff --git a/build-aux/list-distfiles.sh.in b/build-aux/list-distfiles.sh.in
index 91a3758c6..451dece6c 100755
--- a/build-aux/list-distfiles.sh.in
+++ b/build-aux/list-distfiles.sh.in
@@ -19,7 +19,7 @@ am_list () {
printf '%s =' SILEDATA
finder core -name '*.lua' -not -name '*_spec.lua' -not -name 'version.lua' -not -name 'features.lua' -not -name 'pathsetup.lua'
finder classes inputters languages outputters packages shapers types typesetters pagebuilders -name '*.lua' -not -name '*_spec.lua'
-finder classes i18n packages -name '*.ftl'
+finder classes languages packages -name '*.ftl'
finder packages -name '*.svg'
printf '\n\n%s =' LUALIBRARIES
diff --git a/core/languages.lua b/core/languages.lua
index c2b262176..f793c0c82 100644
--- a/core/languages.lua
+++ b/core/languages.lua
@@ -31,7 +31,7 @@ SILE.languageSupport = {
)
)
end
- local ftlresource = string.format("i18n.%s", language)
+ local ftlresource = string.format("languages.%s.messages", language)
SU.debug("fluent", "Loading FTL resource", ftlresource, "into locale", language)
-- This needs to be set so that we load localizations into the right bundle,
-- but this breaks the sync enabled by the hook in the document.language
diff --git a/i18n/tr.ftl b/i18n/tr.ftl
deleted file mode 100644
index 596de94a6..000000000
--- a/i18n/tr.ftl
+++ /dev/null
@@ -1,5 +0,0 @@
-book-chapter-title = Bölüm { $number }
-
-hello = Merhaba { $name }!
-
-tableofcontents-title = İçindekiler
diff --git a/languages/README.md b/languages/README.md
index 06e4787aa..9b529d84b 100644
--- a/languages/README.md
+++ b/languages/README.md
@@ -6,6 +6,10 @@ Supporting a language in SILE involves some combination of:
* A hyphenation patterns module
* Localization strings
+## Localization strings
+
+Each locale may have a `messages.ftl` file that provides translations of strings that may be output into documents.
+
## Hyphenation patterns
Hyphenation rules are typically handled via patterns for the Knuth-Liang hyphenation algorithm.
diff --git a/i18n/af.ftl b/languages/af/messages.ftl
similarity index 100%
rename from i18n/af.ftl
rename to languages/af/messages.ftl
diff --git a/i18n/am.ftl b/languages/am/messages.ftl
similarity index 100%
rename from i18n/am.ftl
rename to languages/am/messages.ftl
diff --git a/i18n/ar.ftl b/languages/ar/messages.ftl
similarity index 100%
rename from i18n/ar.ftl
rename to languages/ar/messages.ftl
diff --git a/i18n/as.ftl b/languages/as/messages.ftl
similarity index 100%
rename from i18n/as.ftl
rename to languages/as/messages.ftl
diff --git a/i18n/bg.ftl b/languages/bg/messages.ftl
similarity index 100%
rename from i18n/bg.ftl
rename to languages/bg/messages.ftl
diff --git a/i18n/bn.ftl b/languages/bn/messages.ftl
similarity index 100%
rename from i18n/bn.ftl
rename to languages/bn/messages.ftl
diff --git a/i18n/bo.ftl b/languages/bo/messages.ftl
similarity index 100%
rename from i18n/bo.ftl
rename to languages/bo/messages.ftl
diff --git a/i18n/ca.ftl b/languages/ca/messages.ftl
similarity index 100%
rename from i18n/ca.ftl
rename to languages/ca/messages.ftl
diff --git a/i18n/cs.ftl b/languages/cs/messages.ftl
similarity index 100%
rename from i18n/cs.ftl
rename to languages/cs/messages.ftl
diff --git a/i18n/cy.ftl b/languages/cy/messages.ftl
similarity index 100%
rename from i18n/cy.ftl
rename to languages/cy/messages.ftl
diff --git a/i18n/da.ftl b/languages/da/messages.ftl
similarity index 100%
rename from i18n/da.ftl
rename to languages/da/messages.ftl
diff --git a/i18n/de.ftl b/languages/de/messages.ftl
similarity index 100%
rename from i18n/de.ftl
rename to languages/de/messages.ftl
diff --git a/i18n/el-monoton.ftl b/languages/el-monoton/messages.ftl
similarity index 100%
rename from i18n/el-monoton.ftl
rename to languages/el-monoton/messages.ftl
diff --git a/i18n/el-polyton.ftl b/languages/el-polyton/messages.ftl
similarity index 100%
rename from i18n/el-polyton.ftl
rename to languages/el-polyton/messages.ftl
diff --git a/i18n/el.ftl b/languages/el/messages.ftl
similarity index 100%
rename from i18n/el.ftl
rename to languages/el/messages.ftl
diff --git a/i18n/en.ftl b/languages/en/messages.ftl
similarity index 100%
rename from i18n/en.ftl
rename to languages/en/messages.ftl
diff --git a/i18n/eo.ftl b/languages/eo/messages.ftl
similarity index 100%
rename from i18n/eo.ftl
rename to languages/eo/messages.ftl
diff --git a/i18n/es.ftl b/languages/es/messages.ftl
similarity index 100%
rename from i18n/es.ftl
rename to languages/es/messages.ftl
diff --git a/i18n/et.ftl b/languages/et/messages.ftl
similarity index 100%
rename from i18n/et.ftl
rename to languages/et/messages.ftl
diff --git a/i18n/eu.ftl b/languages/eu/messages.ftl
similarity index 100%
rename from i18n/eu.ftl
rename to languages/eu/messages.ftl
diff --git a/i18n/fi.ftl b/languages/fi/messages.ftl
similarity index 100%
rename from i18n/fi.ftl
rename to languages/fi/messages.ftl
diff --git a/i18n/fr.ftl b/languages/fr/messages.ftl
similarity index 100%
rename from i18n/fr.ftl
rename to languages/fr/messages.ftl
diff --git a/i18n/ga.ftl b/languages/ga/messages.ftl
similarity index 100%
rename from i18n/ga.ftl
rename to languages/ga/messages.ftl
diff --git a/i18n/gu.ftl b/languages/gu/messages.ftl
similarity index 100%
rename from i18n/gu.ftl
rename to languages/gu/messages.ftl
diff --git a/i18n/hi.ftl b/languages/hi/messages.ftl
similarity index 100%
rename from i18n/hi.ftl
rename to languages/hi/messages.ftl
diff --git a/i18n/hr.ftl b/languages/hr/messages.ftl
similarity index 100%
rename from i18n/hr.ftl
rename to languages/hr/messages.ftl
diff --git a/i18n/hu.ftl b/languages/hu/messages.ftl
similarity index 100%
rename from i18n/hu.ftl
rename to languages/hu/messages.ftl
diff --git a/i18n/hy.ftl b/languages/hy/messages.ftl
similarity index 100%
rename from i18n/hy.ftl
rename to languages/hy/messages.ftl
diff --git a/i18n/id.ftl b/languages/id/messages.ftl
similarity index 100%
rename from i18n/id.ftl
rename to languages/id/messages.ftl
diff --git a/i18n/is.ftl b/languages/is/messages.ftl
similarity index 100%
rename from i18n/is.ftl
rename to languages/is/messages.ftl
diff --git a/i18n/it.ftl b/languages/it/messages.ftl
similarity index 100%
rename from i18n/it.ftl
rename to languages/it/messages.ftl
diff --git a/i18n/ja.ftl b/languages/ja/messages.ftl
similarity index 100%
rename from i18n/ja.ftl
rename to languages/ja/messages.ftl
diff --git a/i18n/jv.ftl b/languages/jv/messages.ftl
similarity index 100%
rename from i18n/jv.ftl
rename to languages/jv/messages.ftl
diff --git a/i18n/ka.ftl b/languages/ka/messages.ftl
similarity index 100%
rename from i18n/ka.ftl
rename to languages/ka/messages.ftl
diff --git a/i18n/kn.ftl b/languages/kn/messages.ftl
similarity index 100%
rename from i18n/kn.ftl
rename to languages/kn/messages.ftl
diff --git a/i18n/la.ftl b/languages/la/messages.ftl
similarity index 100%
rename from i18n/la.ftl
rename to languages/la/messages.ftl
diff --git a/i18n/lt.ftl b/languages/lt/messages.ftl
similarity index 100%
rename from i18n/lt.ftl
rename to languages/lt/messages.ftl
diff --git a/i18n/lv.ftl b/languages/lv/messages.ftl
similarity index 100%
rename from i18n/lv.ftl
rename to languages/lv/messages.ftl
diff --git a/i18n/ml.ftl b/languages/ml/messages.ftl
similarity index 100%
rename from i18n/ml.ftl
rename to languages/ml/messages.ftl
diff --git a/i18n/mr.ftl b/languages/mr/messages.ftl
similarity index 100%
rename from i18n/mr.ftl
rename to languages/mr/messages.ftl
diff --git a/i18n/my.ftl b/languages/my/messages.ftl
similarity index 100%
rename from i18n/my.ftl
rename to languages/my/messages.ftl
diff --git a/i18n/nb.ftl b/languages/nb/messages.ftl
similarity index 100%
rename from i18n/nb.ftl
rename to languages/nb/messages.ftl
diff --git a/i18n/nl.ftl b/languages/nl/messages.ftl
similarity index 100%
rename from i18n/nl.ftl
rename to languages/nl/messages.ftl
diff --git a/i18n/nn.ftl b/languages/nn/messages.ftl
similarity index 100%
rename from i18n/nn.ftl
rename to languages/nn/messages.ftl
diff --git a/i18n/no.ftl b/languages/no/messages.ftl
similarity index 100%
rename from i18n/no.ftl
rename to languages/no/messages.ftl
diff --git a/i18n/or.ftl b/languages/or/messages.ftl
similarity index 100%
rename from i18n/or.ftl
rename to languages/or/messages.ftl
diff --git a/i18n/pa.ftl b/languages/pa/messages.ftl
similarity index 100%
rename from i18n/pa.ftl
rename to languages/pa/messages.ftl
diff --git a/i18n/pl.ftl b/languages/pl/messages.ftl
similarity index 100%
rename from i18n/pl.ftl
rename to languages/pl/messages.ftl
diff --git a/i18n/pt.ftl b/languages/pt/messages.ftl
similarity index 100%
rename from i18n/pt.ftl
rename to languages/pt/messages.ftl
diff --git a/i18n/rm.ftl b/languages/rm/messages.ftl
similarity index 100%
rename from i18n/rm.ftl
rename to languages/rm/messages.ftl
diff --git a/i18n/ro.ftl b/languages/ro/messages.ftl
similarity index 100%
rename from i18n/ro.ftl
rename to languages/ro/messages.ftl
diff --git a/i18n/ru.ftl b/languages/ru/messages.ftl
similarity index 100%
rename from i18n/ru.ftl
rename to languages/ru/messages.ftl
diff --git a/i18n/sa.ftl b/languages/sa/messages.ftl
similarity index 100%
rename from i18n/sa.ftl
rename to languages/sa/messages.ftl
diff --git a/i18n/sk.ftl b/languages/sk/messages.ftl
similarity index 100%
rename from i18n/sk.ftl
rename to languages/sk/messages.ftl
diff --git a/i18n/sl.ftl b/languages/sl/messages.ftl
similarity index 100%
rename from i18n/sl.ftl
rename to languages/sl/messages.ftl
diff --git a/i18n/sr.ftl b/languages/sr/messages.ftl
similarity index 100%
rename from i18n/sr.ftl
rename to languages/sr/messages.ftl
diff --git a/i18n/sv.ftl b/languages/sv/messages.ftl
similarity index 100%
rename from i18n/sv.ftl
rename to languages/sv/messages.ftl
diff --git a/i18n/ta.ftl b/languages/ta/messages.ftl
similarity index 100%
rename from i18n/ta.ftl
rename to languages/ta/messages.ftl
diff --git a/i18n/th.ftl b/languages/th/messages.ftl
similarity index 100%
rename from i18n/th.ftl
rename to languages/th/messages.ftl
diff --git a/i18n/tk.ftl b/languages/tk/messages.ftl
similarity index 100%
rename from i18n/tk.ftl
rename to languages/tk/messages.ftl
diff --git a/languages/tr/messages.ftl b/languages/tr/messages.ftl
new file mode 100644
index 000000000..2dae95d1c
--- /dev/null
+++ b/languages/tr/messages.ftl
@@ -0,0 +1,15 @@
+bibliography-and = ve
+
+bibliography-edited-by = { $name } tarafından düzenlendi
+
+bibliography-et-al = ve ark.
+
+bibliography-translated-by = { $name } tarafından tercüme edildi
+
+book-chapter-title = Bölüm { $number }
+
+hello = Merhaba { $name }!
+
+tableofcontents-not-generated = İçindekiler tablosunu işlemek için SİLE'yi yeniden çalıştırın!
+
+tableofcontents-title = İçindekiler
diff --git a/i18n/ug.ftl b/languages/ug/messages.ftl
similarity index 100%
rename from i18n/ug.ftl
rename to languages/ug/messages.ftl
diff --git a/i18n/uk.ftl b/languages/uk/messages.ftl
similarity index 100%
rename from i18n/uk.ftl
rename to languages/uk/messages.ftl
diff --git a/i18n/und.ftl b/languages/und/messages.ftl
similarity index 71%
rename from i18n/und.ftl
rename to languages/und/messages.ftl
index 84e366897..8fd94eddd 100644
--- a/i18n/und.ftl
+++ b/languages/und/messages.ftl
@@ -1,3 +1,5 @@
+bibliography-et-al = et al.
+
hello = Namárië { $name }!
tableofcontents-not-generated = Rerun SILE to process the table of contents!
diff --git a/i18n/ur.ftl b/languages/ur/messages.ftl
similarity index 100%
rename from i18n/ur.ftl
rename to languages/ur/messages.ftl
diff --git a/i18n/yue.ftl b/languages/yue/messages.ftl
similarity index 100%
rename from i18n/yue.ftl
rename to languages/yue/messages.ftl
diff --git a/i18n/zh-hans.ftl b/languages/zh-hans/messages.ftl
similarity index 100%
rename from i18n/zh-hans.ftl
rename to languages/zh-hans/messages.ftl
diff --git a/i18n/zh-hant.ftl b/languages/zh-hant/messages.ftl
similarity index 100%
rename from i18n/zh-hant.ftl
rename to languages/zh-hant/messages.ftl