Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i18n #486

Open
1 of 3 tasks
srid opened this issue Dec 28, 2023 · 5 comments
Open
1 of 3 tasks

i18n #486

srid opened this issue Dec 28, 2023 · 5 comments
Labels
enhancement New feature or request

Comments

@srid
Copy link
Owner

srid commented Dec 28, 2023

What can Emanote do to better support multilingual websites?

For original requirement, see this issue nixos-asia/website#18 (cc @brsvh)

Tasks

@srid srid added the enhancement New feature or request label Dec 28, 2023
@brsvh
Copy link

brsvh commented Jan 23, 2024

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.

name: /templates/layouts/default

@srid
Copy link
Owner Author

srid commented Jan 23, 2024

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}"> 

@brsvh
Copy link

brsvh commented Jan 24, 2024

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?

@srid
Copy link
Owner Author

srid commented Jan 30, 2024

@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:

data ModelT encF = Model
{ _modelStatus :: Status
, _modelLayers :: Set Loc
, _modelEmaCLIAction :: Ema.CLI.Action
, _modelRoutePrism :: encF (Prism' FilePath SiteRoute)
, _modelPandocRenderers :: EmanotePandocRenderers Model LMLRoute
-- ^ Dictates how exactly to render `Pandoc` to Heist nodes.
, _modelCompileTailwind :: Bool
, _modelInstanceID :: UUID
-- ^ An unique ID for this process's model. ID changes across processes.
, _modelNotes :: IxNote
, _modelRels :: IxRel
, _modelSData :: IxSData
, _modelStaticFiles :: IxStaticFile
, _modelTasks :: IxTask
-- ^ A tree (forest) of all notes, based on their folder hierarchy.
, _modelHeistTemplate :: TemplateState
, _modelStorkIndex :: Stork.IndexVar
, _modelFolgezettelTree :: Forest R.LMLRoute
-- ^ Folgezettel tree computed once for each update to model.
}

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.

@srid
Copy link
Owner Author

srid commented Jan 30, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants