multi-lang by file base
Create a multi-lang site by writing articles with the following structure.
- posts/2024-05-28-filename-en.md
- posts/2024-05-28-filename-jp.md
specific example
This site is being created with the above structure. The engine part will be separated and released at a later date.
modify Route
First, change the Route. The following is an image of the change.
- path: original source
- posts/2024-05-28-filename-en.md
- posts/2024-05-28-filename-jp.md
- path: converted html
- en/2024-05-28-filename.html
- jp/2024-05-28-filename.html
Excerpt : codes of Route
match (fromArticle "posts/*") $ do
route langRoutelangRoute :: Routes
langRoute = customRoute ((`replaceExtension` ".html") . getLangPath)
langseperator :: String
langseperator = "-"
takeLang :: Identifier -> String
takeLang = last . splitAll langseperator . takeBaseName . toFilePath
dropLang :: Identifier -> String
dropLang = L.intercalate langseperator . init . splitAll langseperator . toFilePath
getLangPath :: Identifier -> String
getLangPath id = lang `combine` dropLang id
where
lang = takeLang idThe operations being performed are simple and include the following
- get filepath from
Identifier - pick lang-code such as like
-en,-jp - swap and re-concat with
/
embed link which another lang
It is achieved as follows.
- search same
filenamefromIdentifiersuch as :filename-lang.md - put link which search result
anothorLangFields :: String -> Snapshot -> Context String
anothorLangFields name snapshot = listFieldWith name baseCtx f
where
f item = loadAllSnapshots (fromGlob (mainname ++ "*")) snapshot
where
id = itemIdentifier item
mainname = dropLang id
lang = takeLang idbelow is how to use anothorLangFields.
- make
snapshot - apply
templatewithpostCtx
match (fromArticle "posts/*") $ do
route langRoute
compile $ do
pandocCompiler
>>= saveSnapshot "posts-content"
>>= loadAndApplyTemplate (idBase "templates/post.html") postCtxpostCtxis to connectbaseCtxandanothorLangFields.
postCtx :: Context String
postCtx =
baseCtx
`mappend` anothorLangFields "anothorLangs" "posts-content"baseCtx: a context to embed basic info
baseCtx :: Context String
baseCtx =
dateField "date" "%Y/%m/%d"
`mappend` dateFieldMeta "last-modified" "last-modified" "%Y/%m/%d"
`mappend` readTimeField "readtime" "posts-content"
`mappend` langField "lang"
`mappend` sameLangField "home" "index"
`mappend` defaultContextThe context now has the following structure
- date
- last-modified
- readtime
- lang
- home
- (defaultContext)
- anotherlangs
- date
- last-modified
- readtime
- lang
- home
- (defaultContext)
It can be called as like below in template.
$for(anothorLangs)$
<tr>
<td>
<a href="$url$">$title$ ($lang$)</a>
</td>
<td>$date$</td>
<td>$if(last-modified)$ $last-modified$ $else$ $date$ $endif$</td>
</tr>
$endfor$to use inter link in md with modified Route
This is separated into a separate page due to its more general content.
to use inter link in md with modified Route by Hakyll
to reconstruct post list
-en.md and -jp.md will be lined up respectively if posts/*.md read in this file-based system.
but necessary is unieque one of same file in posts/file-lang.md.
apply filterUniqs againstposts/* like the following and save only unique file.
compile $ do
posts <- recentFirst . filterUniqs =<< loadAllSnapshots "posts/*" "posts-content"filterUniqs is a function to reconstruct [Item String].
pick files which filename dropped a part -lang is not same.
and concat picked items. and make a list to concated it.
filterUniqs :: [Item String] -> [Item String]
filterUniqs [] = []
filterUniqs (x : xs) = x : filterUniqs (filter ((/= f x) . f) xs)
where
f = dropLang . itemIdentifierThis will achieve the expected operation.