i18n
srid opened this issue · 5 comments
What can Emanote do to better support multilingual websites?
For original requirement, see this issue nixos-asia/website#18 (cc @brsvh)
Tasks
- #485
-
.tpl
templates should support translated strings (based onpage.lang
) - ...
I am currently attempting to move the templates into directories named after their respective languages, such as {en,zh-Hans}/components/sidebar.tpl
. Do you find this style appropriate?
In this case, we need to implement different components for different languages, though the variations are minimal, for instance:
<nav id="sidebar"
class="flex-shrink hidden leading-relaxed md:block md:sticky md:top-0 md:max-h-screen md:overflow-y-auto md:w-48 xl:w-64">
<div class="px-2 py-2 text-gray-800">
<div id="indexing-links" class="flex flex-row float-right p-2 space-x-2 text-gray-500">
<a href="${ema:tagIndexUrl}" title="标签"> <!-- only changed here -->
<svg style="width: 1rem;" class="hover:text-${theme}-700" fill="none" stroke="currentColor"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z">
</path>
</svg>
</a>
This approach seems somewhat verbose, do you have any alternative suggestions?
Moreover, this method cannot be applied to layouts, as the default layout location has been hardcoded at here.
emanote/emanote/default/index.yaml
Line 14 in 36d27aa
I don't think we should have per-language templates. Instead, the default layer should support translation somehow.
[I added a todo to issue description to this effect]
Perhaps we can have a strings table in Haskell that is indexed by language (page.lang
yaml frontmatter), and then pass the approproriate language table to Heist as template var (see Template.hs
), which then gets used in .tpl
files instead of inline English text. What do you think?
So it would look like,
<a href="${ema:tagIndexUrl}" title="${strings:tagIndexTitle}">
Yes, I share the same opinion.
It appears that for page interface elements, we can make a simple convention for looking up multilingual dictionaries. By having Haskell parse a table at a designated location to bind the variables that will be used in the templates. For example, templates/i18n/{en,fr}/translations.json
:
# en
{
"tagIndexTitle": "foo",
...
}
# fr
{
"tagIndexTitle": "bar",
...
}
However, during static website generation, we need to pass all translations to fill in the strings. A variable may have multiple corresponding values, so how should variable bindings in the template be handled?
@brsvh You can create a Haskell type like,
newtype TranslationTable = TranslationTable { unTranslationTable :: Map Lang (Map Text Text) }
-- | Parse translations.json from notebook
parseTranslations :: FilePath -> IO (Either Text TranslationTable)
parseTranslations = undefined
-- | Get effective translations for given lang (falling back to English when an entry is missing)
tableFor :: TranslationTable -> Lang -> Map Text Text
tableFor = ...
Then, you store the TranslationTable
in the Model
type here:
emanote/emanote/src/Emanote/Model/Type.hs
Lines 50 to 70 in 6463657
Then you can pass tableFor
as json template var (see Template.hs
), and access them from templates. Once in templates, they work the same in both live server and static site.
If you need more help, let me know.
A variable may have multiple corresponding values, so how should variable bindings in the template be handled?
Oh, you would choose them from page.lang
property (falling back to the en
default). But all of this happens in Haskell (tableFor
above), not the templates.