Constants for language access
This commit is contained in:
parent
f4201bea7a
commit
da7cf45f8a
@ -4,12 +4,8 @@ import kotlinx.html.body
|
||||
import kotlinx.html.head
|
||||
import kotlinx.html.title
|
||||
import space.kscience.dataforge.data.Data
|
||||
import space.kscience.dataforge.data.getItem
|
||||
import space.kscience.dataforge.meta.*
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.asName
|
||||
import space.kscience.dataforge.names.plus
|
||||
import space.kscience.dataforge.names.removeHeadOrNull
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
/**
|
||||
@ -21,63 +17,24 @@ public interface DataRenderer {
|
||||
public operator fun invoke(name: Name, data: Data<Any>)
|
||||
|
||||
public companion object {
|
||||
|
||||
// context (SiteBuilder)
|
||||
// public fun buildPageMeta(name: Name, data: Data<Any>): Laminate {
|
||||
// val languages = languages.mapKeys { it.value["key"]?.string ?: it.key }
|
||||
//
|
||||
// // detect current language by prefix if it is not defined explicitly
|
||||
// val currentLanguage: String = data.meta["language"]?.string
|
||||
// ?: languages.keys.firstOrNull() { key -> name.startsWith(key.parseAsName()) } ?: defaultLanguage
|
||||
//
|
||||
// //
|
||||
// val languageMap = Meta {
|
||||
// languages.forEach { (key, meta) ->
|
||||
// val languagePrefix: String = meta.string ?: meta["name"]?.string ?: return@forEach
|
||||
// val targetName = name.removeHeadOrNull("")
|
||||
// val targetData = this@SiteBuilder.data[targetName.parseAsName()]
|
||||
// if (targetData != null) key put targetName
|
||||
// }
|
||||
// }
|
||||
// val languageMeta = Meta {
|
||||
// "language" put currentLanguage
|
||||
// if (!languageMap.isEmpty()) {
|
||||
// "languageMap" put languageMap
|
||||
// }
|
||||
// }
|
||||
// return Laminate(data.meta, languageMeta, siteMeta)
|
||||
// }
|
||||
|
||||
/**
|
||||
* Automatically build a language map for a data piece with given [name] based on existence of appropriate data nodes.
|
||||
*/
|
||||
context(SiteBuilder)
|
||||
public fun buildLanguageMeta(name: Name): Meta = Meta {
|
||||
val currentLanguagePrefix = languages[language]?.get("prefix")?.string ?: language
|
||||
val fullName = (route.removeHeadOrNull(currentLanguagePrefix.asName()) ?: route) + name
|
||||
languages.forEach { (key, meta) ->
|
||||
val languagePrefix: String = meta["prefix"].string ?: key
|
||||
val nameWithLanguage: Name = if (languagePrefix.isBlank()) {
|
||||
fullName
|
||||
} else {
|
||||
languagePrefix.asName() + fullName
|
||||
}
|
||||
if (data.getItem(name) != null) {
|
||||
key put meta.asMutableMeta().apply {
|
||||
"target" put nameWithLanguage.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public val DEFAULT: DataRenderer = object : DataRenderer {
|
||||
|
||||
context(SiteBuilder)
|
||||
override fun invoke(name: Name, data: Data<Any>) {
|
||||
if (data.type == typeOf<HtmlData>()) {
|
||||
page(name, data.meta) {
|
||||
val languageMeta: Meta = Language.forName(name)
|
||||
|
||||
val dataMeta: Meta = if (languageMeta.isEmpty()) {
|
||||
data.meta
|
||||
} else {
|
||||
data.meta.toMutableMeta().apply {
|
||||
"languages" put languageMeta
|
||||
}
|
||||
}
|
||||
|
||||
page(name, dataMeta) {
|
||||
head {
|
||||
title = data.meta["title"].string ?: "Untitled page"
|
||||
title = dataMeta["title"].string ?: "Untitled page"
|
||||
}
|
||||
body {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
147
snark-html/src/main/kotlin/space/kscience/snark/html/Language.kt
Normal file
147
snark-html/src/main/kotlin/space/kscience/snark/html/Language.kt
Normal file
@ -0,0 +1,147 @@
|
||||
package space.kscience.snark.html
|
||||
|
||||
import space.kscience.dataforge.data.getItem
|
||||
import space.kscience.dataforge.meta.*
|
||||
import space.kscience.dataforge.names.*
|
||||
import space.kscience.snark.html.Language.Companion.SITE_LANGUAGES_KEY
|
||||
import space.kscience.snark.html.Language.Companion.SITE_LANGUAGE_KEY
|
||||
|
||||
|
||||
|
||||
public class Language : Scheme() {
|
||||
/**
|
||||
* Language key override
|
||||
*/
|
||||
public var key: String? by string()
|
||||
|
||||
/**
|
||||
* Page name prefix
|
||||
*/
|
||||
public var prefix: String? by string()
|
||||
|
||||
/**
|
||||
* Target page name with a given language key
|
||||
*/
|
||||
public var target: Name?
|
||||
get() = meta["target"].string?.parseAsName(false)
|
||||
set(value) {
|
||||
meta["target"] = value?.toString()?.asValue()
|
||||
}
|
||||
|
||||
public companion object : SchemeSpec<Language>(::Language) {
|
||||
|
||||
public val LANGUAGE_KEY: Name = "language".asName()
|
||||
|
||||
public val LANGUAGES_KEY: Name = "languages".asName()
|
||||
|
||||
public val SITE_LANGUAGE_KEY: Name = SiteBuilder.SITE_META_KEY + LANGUAGE_KEY
|
||||
|
||||
public val SITE_LANGUAGES_KEY: Name = SiteBuilder.SITE_META_KEY + LANGUAGES_KEY
|
||||
|
||||
public const val DEFAULT_LANGUAGE: String = "en"
|
||||
|
||||
/**
|
||||
* Automatically build a language map for a data piece with given [name] based on existence of appropriate data nodes.
|
||||
*/
|
||||
context(SiteBuilder)
|
||||
public fun forName(name: Name): Meta = Meta {
|
||||
val currentLanguagePrefix = languages[language]?.get(Language::prefix.name)?.string ?: language
|
||||
val fullName = (route.removeHeadOrNull(currentLanguagePrefix.asName()) ?: route) + name
|
||||
languages.forEach { (key, meta) ->
|
||||
val languagePrefix: String = meta[Language::prefix.name].string ?: key
|
||||
val nameWithLanguage: Name = if (languagePrefix.isBlank()) {
|
||||
fullName
|
||||
} else {
|
||||
languagePrefix.asName() + fullName
|
||||
}
|
||||
if (data.getItem(name) != null) {
|
||||
key put meta.asMutableMeta().apply {
|
||||
Language::target.name put nameWithLanguage.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public val SiteBuilder.languages: Map<String, Meta>
|
||||
get() = siteMeta[SITE_LANGUAGES_KEY]?.items?.mapKeys { it.key.toStringUnescaped() } ?: emptyMap()
|
||||
|
||||
public val SiteBuilder.language: String
|
||||
get() = siteMeta[SITE_LANGUAGE_KEY].string ?: Language.DEFAULT_LANGUAGE
|
||||
|
||||
public val SiteBuilder.languagePrefix: Name
|
||||
get() = languages[language]?.let { it[Language::prefix.name].string ?: language }?.parseAsName() ?: Name.EMPTY
|
||||
|
||||
public fun SiteBuilder.withLanguages(languageMap: Map<String, Meta>, block: SiteBuilder.(language: String) -> Unit) {
|
||||
languageMap.forEach { (languageKey, languageMeta) ->
|
||||
val prefix = languageMeta[Language::prefix.name].string ?: languageKey
|
||||
val routeMeta = Meta {
|
||||
SITE_LANGUAGE_KEY put languageKey
|
||||
SITE_LANGUAGES_KEY put Meta {
|
||||
languageMap.forEach {
|
||||
it.key put it.value
|
||||
}
|
||||
}
|
||||
}
|
||||
route(prefix, routeMeta = routeMeta) {
|
||||
block(languageKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public fun SiteBuilder.withLanguages(
|
||||
vararg language: Pair<String, String>,
|
||||
block: SiteBuilder.(language: String) -> Unit,
|
||||
) {
|
||||
val languageMap = language.associate {
|
||||
it.first to Meta {
|
||||
Language::prefix.name put it.second
|
||||
}
|
||||
}
|
||||
withLanguages(languageMap, block)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The language key of this page
|
||||
*/
|
||||
public val WebPage.language: String
|
||||
get() = pageMeta[Language.LANGUAGE_KEY]?.string ?: pageMeta[SITE_LANGUAGE_KEY]?.string ?: Language.DEFAULT_LANGUAGE
|
||||
|
||||
/**
|
||||
* Mapping of language keys to other language versions of this page
|
||||
*/
|
||||
public val WebPage.languages: Map<String, Meta>
|
||||
get() = pageMeta[Language.LANGUAGES_KEY]?.items?.mapKeys { it.key.toStringUnescaped() } ?: emptyMap()
|
||||
|
||||
public fun WebPage.localisedPageRef(pageName: Name, relative: Boolean = false): String {
|
||||
val prefix = languages[language]?.get(Language::prefix.name)?.string?.parseAsName() ?: Name.EMPTY
|
||||
return resolvePageRef(prefix + pageName, relative)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render all pages in a node with given name. Use localization prefix if appropriate data is available.
|
||||
*/
|
||||
public fun SiteBuilder.localizedPages(
|
||||
dataPath: Name,
|
||||
remotePath: Name = dataPath,
|
||||
dataRenderer: DataRenderer = DataRenderer.DEFAULT,
|
||||
) {
|
||||
val item = data.getItem(languagePrefix + dataPath)
|
||||
?: data.getItem(dataPath)
|
||||
?: error("No data found by name $dataPath")
|
||||
route(remotePath) {
|
||||
pages(item, dataRenderer)
|
||||
}
|
||||
}
|
||||
|
||||
public fun SiteBuilder.localizedPages(
|
||||
dataPath: String,
|
||||
remotePath: Name = dataPath.parseAsName(),
|
||||
dataRenderer: DataRenderer = DataRenderer.DEFAULT,
|
||||
) {
|
||||
localizedPages(dataPath.parseAsName(), remotePath, dataRenderer = dataRenderer)
|
||||
}
|
@ -89,6 +89,7 @@ public interface SiteBuilder : ContextAware, SnarkContext {
|
||||
|
||||
|
||||
public companion object {
|
||||
public val SITE_META_KEY: Name = "site".asName()
|
||||
public val INDEX_PAGE_TOKEN: NameToken = NameToken("index")
|
||||
public val UP_PAGE_TOKEN: NameToken = NameToken("..")
|
||||
}
|
||||
|
@ -1,88 +0,0 @@
|
||||
package space.kscience.snark.html
|
||||
|
||||
import space.kscience.dataforge.data.getItem
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.meta.get
|
||||
import space.kscience.dataforge.meta.string
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.parseAsName
|
||||
import space.kscience.dataforge.names.plus
|
||||
|
||||
public val SiteBuilder.languages: Map<String, Meta>
|
||||
get() = siteMeta["site.languages"]?.items?.mapKeys { it.key.toStringUnescaped() } ?: emptyMap()
|
||||
|
||||
public val SiteBuilder.language: String
|
||||
get() = siteMeta["site.language"].string ?: "en"
|
||||
|
||||
public val SiteBuilder.languagePrefix: Name
|
||||
get() = languages[language]?.let { it["prefix"].string ?: language }?.parseAsName() ?: Name.EMPTY
|
||||
|
||||
public fun SiteBuilder.withLanguages(languageMap: Map<String, Meta>, block: SiteBuilder.(language: String) -> Unit) {
|
||||
languageMap.forEach { (languageKey, languageMeta) ->
|
||||
val prefix = languageMeta["prefix"].string ?: languageKey
|
||||
val routeMeta = Meta {
|
||||
"site.language" put languageKey
|
||||
"site.languages" put Meta {
|
||||
languageMap.forEach {
|
||||
it.key put it.value
|
||||
}
|
||||
}
|
||||
}
|
||||
route(prefix, routeMeta = routeMeta) {
|
||||
block(languageKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public fun SiteBuilder.withLanguages(
|
||||
vararg language: Pair<String, String>,
|
||||
block: SiteBuilder.(language: String) -> Unit,
|
||||
) {
|
||||
val languageMap = language.associate {
|
||||
it.first to Meta {
|
||||
"prefix" put it.second
|
||||
}
|
||||
}
|
||||
withLanguages(languageMap, block)
|
||||
}
|
||||
|
||||
/**
|
||||
* The language key of this page
|
||||
*/
|
||||
public val WebPage.language: String get() = pageMeta["language"]?.string ?: pageMeta["site.language"]?.string ?: "en"
|
||||
|
||||
/**
|
||||
* Mapping of language keys to other language versions of this page
|
||||
*/
|
||||
public val WebPage.languages: Map<String, Meta>
|
||||
get() = pageMeta["languages"]?.items?.mapKeys { it.key.toStringUnescaped() } ?: emptyMap()
|
||||
|
||||
public fun WebPage.localisedPageRef(pageName: Name, relative: Boolean = false): String {
|
||||
val prefix = languages[language]?.get("prefix")?.string?.parseAsName() ?: Name.EMPTY
|
||||
return resolvePageRef(prefix + pageName, relative)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render all pages in a node with given name. Use localization prefix if appropriate data is available.
|
||||
*/
|
||||
public fun SiteBuilder.localizedPages(
|
||||
dataPath: Name,
|
||||
remotePath: Name = dataPath,
|
||||
dataRenderer: DataRenderer = DataRenderer.DEFAULT,
|
||||
) {
|
||||
val item = data.getItem(languagePrefix + dataPath)
|
||||
?: data.getItem(dataPath)
|
||||
?: error("No data found by name $dataPath")
|
||||
route(remotePath) {
|
||||
pages(item, dataRenderer)
|
||||
}
|
||||
}
|
||||
|
||||
public fun SiteBuilder.localizedPages(
|
||||
dataPath: String,
|
||||
remotePath: Name = dataPath.parseAsName(),
|
||||
dataRenderer: DataRenderer = DataRenderer.DEFAULT,
|
||||
) {
|
||||
localizedPages(dataPath.parseAsName(), remotePath, dataRenderer = dataRenderer)
|
||||
}
|
Loading…
Reference in New Issue
Block a user