Skip to content

Commit

Permalink
refactor: make translations global
Browse files Browse the repository at this point in the history
  • Loading branch information
d1snin committed May 2, 2024
1 parent 19492ca commit 3766cc5
Show file tree
Hide file tree
Showing 37 changed files with 1,450 additions and 1,910 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ import dev.d1s.beam.bundle.html.RenderParameters
import dev.d1s.beam.bundle.html.UrlPreviewMetaTags
import dev.d1s.beam.bundle.response.Defaults
import dev.d1s.beam.client.BeamClient
import dev.d1s.beam.commons.*
import dev.d1s.beam.commons.LanguageCode
import dev.d1s.beam.commons.Space
import dev.d1s.beam.commons.SpaceFavicon
import dev.d1s.beam.commons.SpaceUrlPreview
import io.ktor.client.plugins.*
import io.ktor.http.*
import org.koin.core.component.KoinComponent
Expand Down Expand Up @@ -59,7 +62,7 @@ class DefaultIndexService : IndexService, KoinComponent {

spaceId ?: return resolveNotAvailableSpace()

val languageCode = resolveLanguageCode(spaceId)
val languageCode = resolveLanguageCode()
val spaceResult = client.getSpace(spaceId, languageCode)

spaceResult.onFailure {
Expand Down Expand Up @@ -162,6 +165,6 @@ class DefaultIndexService : IndexService, KoinComponent {
return ResolvedSpace(space, html)
}

private suspend fun resolveLanguageCode(spaceId: SpaceIdentifier) =
client.getResolvedTranslation(spaceId, Defaults.LANGUAGE_CODE).getOrNull()?.languageCode
private suspend fun resolveLanguageCode() =
client.getResolvedTranslation(Defaults.LANGUAGE_CODE).getOrNull()?.languageCode
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,29 @@
package dev.d1s.beam.client.app.state

import dev.d1s.beam.client.TranslationModificationBuilder
import dev.d1s.beam.client.app.ApplicationContext
import dev.d1s.beam.commons.LanguageCode
import io.ktor.client.plugins.*
import io.ktor.http.*
import org.lighthousegames.logging.logging

private val log = logging()

public suspend fun SpaceContext.translation(configure: suspend TranslationModificationBuilder.() -> Unit) {
val space = space.id

public suspend fun ApplicationContext.translation(
languageCode: LanguageCode,
configure: suspend TranslationModificationBuilder.() -> Unit
) {
val modification = TranslationModificationBuilder().apply { configure() }.buildTranslationModification()

log.i {
"Creating translation for space '$space' in language '${modification.languageCode}'..."
"Creating translation in language '$languageCode'..."
}

client.postTranslation(space, modification).getOrElse {
client.postTranslation(languageCode, modification).getOrElse {
val isConflict = it is ClientRequestException && it.response.status == HttpStatusCode.Conflict

if (isConflict) {
client.putTranslation(space, modification.languageCode, modification).getOrThrow()
client.putTranslation(languageCode, modification).getOrThrow()
} else {
throw it
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,37 +138,32 @@ public interface BeamClient {
): Result<Row>

public suspend fun postTranslation(
spaceId: SpaceIdentifier? = null,
languageCode: LanguageCode,
translation: TranslationModification
): Result<Translation>

public suspend fun postTranslation(
spaceId: SpaceIdentifier? = null,
languageCode: LanguageCode,
configure: suspend TranslationModificationBuilder.() -> Unit
): Result<Translation>

public suspend fun getTranslation(spaceId: SpaceIdentifier? = null, languageCode: LanguageCode): Result<Translation>
public suspend fun getTranslation(languageCode: LanguageCode): Result<Translation>

public suspend fun getResolvedTranslation(
spaceId: SpaceIdentifier? = null,
languageCode: LanguageCode
): Result<Translation>
public suspend fun getResolvedTranslation(languageCode: LanguageCode): Result<Translation>

public suspend fun getTranslations(spaceId: SpaceIdentifier? = null): Result<Translations>
public suspend fun getTranslations(): Result<Translations>

public suspend fun putTranslation(
spaceId: SpaceIdentifier? = null,
languageCode: LanguageCode,
translation: TranslationModification
): Result<Translation>

public suspend fun putTranslation(
spaceId: SpaceIdentifier? = null,
languageCode: LanguageCode,
configure: suspend TranslationModificationBuilder.() -> Unit
): Result<Translation>

public suspend fun deleteTranslation(spaceId: SpaceIdentifier? = null, languageCode: LanguageCode): Result<Unit>
public suspend fun deleteTranslation(languageCode: LanguageCode): Result<Unit>

public suspend fun onSpaceCreated(block: suspend (ClientWebSocketEvent<Space>) -> Unit): Result<Job>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ public class DefaultBeamClient(
)

override suspend fun postTranslation(
spaceId: SpaceIdentifier?,
languageCode: LanguageCode,
translation: TranslationModification
): Result<Translation> =
runCatching {
Expand All @@ -332,45 +332,38 @@ public class DefaultBeamClient(
httpClient.post(Paths.POST_TRANSLATION) {
contentType(ContentType.Application.Json)
setBody(translation)
setSpaceId(spaceId)
}.body()
}

override suspend fun postTranslation(
spaceId: SpaceIdentifier?,
languageCode: LanguageCode,
configure: suspend TranslationModificationBuilder.() -> Unit
): Result<Translation> =
postTranslation(spaceId, TranslationModificationBuilder().apply { configure() }.buildTranslationModification())
postTranslation(
languageCode,
TranslationModificationBuilder().apply { configure() }.buildTranslationModification()
)

override suspend fun getTranslation(spaceId: SpaceIdentifier?, languageCode: LanguageCode): Result<Translation> =
override suspend fun getTranslation(languageCode: LanguageCode): Result<Translation> =
runCatching {
val path = Paths.GET_TRANSLATION.replaceLanguageCodePlaceholder(languageCode)

httpClient.get(path) {
setSpaceId(spaceId)
}.body()
httpClient.get(path).body()
}

public override suspend fun getResolvedTranslation(
spaceId: SpaceIdentifier?,
languageCode: LanguageCode
): Result<Translation> =
public override suspend fun getResolvedTranslation(languageCode: LanguageCode): Result<Translation> =
runCatching {
httpClient.get(Paths.GET_RESOLVED_TRANSLATION) {
setSpaceId(spaceId)
setLanguageCode(languageCode)
}.body()
}

override suspend fun getTranslations(spaceId: SpaceIdentifier?): Result<Translations> =
override suspend fun getTranslations(): Result<Translations> =
runCatching {
httpClient.get(Paths.GET_TRANSLATIONS) {
setSpaceId(spaceId)
}.body()
httpClient.get(Paths.GET_TRANSLATIONS).body()
}

override suspend fun putTranslation(
spaceId: SpaceIdentifier?,
languageCode: LanguageCode,
translation: TranslationModification
): Result<Translation> =
Expand All @@ -382,30 +375,25 @@ public class DefaultBeamClient(
httpClient.put(path) {
contentType(ContentType.Application.Json)
setBody(translation)
setSpaceId(spaceId)
}.body()
}

override suspend fun putTranslation(
spaceId: SpaceIdentifier?,
languageCode: LanguageCode,
configure: suspend TranslationModificationBuilder.() -> Unit
): Result<Translation> =
putTranslation(
spaceId,
languageCode,
TranslationModificationBuilder().apply { configure() }.buildTranslationModification()
)

override suspend fun deleteTranslation(spaceId: SpaceIdentifier?, languageCode: LanguageCode): Result<Unit> =
override suspend fun deleteTranslation(languageCode: LanguageCode): Result<Unit> =
runCatching {
requireToken()

val path = Paths.DELETE_TRANSLATION.replaceLanguageCodePlaceholder(languageCode)

httpClient.delete(path) {
setSpaceId(spaceId)
}
httpClient.delete(path)
}

override suspend fun onSpaceCreated(block: suspend (ClientWebSocketEvent<Space>) -> Unit): Result<Job> =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ import dev.d1s.beam.commons.*
@BuilderDsl
public class TranslationModificationBuilder {

public var languageCode: LanguageCode? = null

public var languageName: LanguageName? = null

public var default: Boolean? = null
Expand All @@ -35,7 +33,6 @@ public class TranslationModificationBuilder {

public fun buildTranslationModification(): TranslationModification =
TranslationModification(
languageCode ?: error("Translation language code is undefined"),
languageName,
default ?: error("Translation default status is undefined"),
translations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,9 @@ public object GlobalTranslation {
)

public val Default: Translation = Translation(
space = null,
languageCode = "en",
languageName = "English",
default = false,
default = true,
translations = mapOf(
LOCATION_ICON_ALT to "Beam space icon",
LOCATION_DEFAULT_TITLE to "Beam",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ public object Paths {
public const val GET_ROWS: String = "/api/rows"
public const val PUT_ROW: String = "/api/rows/{${ID_PARAMETER}}"

public const val POST_TRANSLATION: String = "/api/translations"
public const val POST_TRANSLATION: String = "/api/translations/{$LANGUAGE_CODE_PARAMETER}"
public const val GET_TRANSLATION: String = "/api/translations/{$LANGUAGE_CODE_PARAMETER}"
public const val GET_RESOLVED_TRANSLATION: String = "/api/translation"
public const val GET_RESOLVED_TRANSLATION: String = "/api/translation/{$LANGUAGE_CODE_PARAMETER}"
public const val GET_TRANSLATIONS: String = "/api/translations"
public const val PUT_TRANSLATION: String = "/api/translations"
public const val PUT_TRANSLATION: String = "/api/translations/{$LANGUAGE_CODE_PARAMETER}"
public const val DELETE_TRANSLATION: String = "/api/translations/{$LANGUAGE_CODE_PARAMETER}"
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,8 @@ public typealias Translations = List<Translation>

public val TextLocation.asTemplate: Template get() = "\${$this}"

public fun TranslationQualifier(spaceId: SpaceId?, languageCode: LanguageCode): TranslationQualifier =
(spaceId?.let { "$it-" } ?: "") + languageCode

public sealed interface AbstractTranslation {

public val languageCode: LanguageCode

public val languageName: LanguageName?

public val default: Boolean
Expand All @@ -51,16 +46,14 @@ public sealed interface AbstractTranslation {

@Serializable
public data class Translation(
val space: SpaceId?,
override val languageCode: LanguageCode,
val languageCode: LanguageCode,
override val languageName: LanguageName,
override val default: Boolean,
override val translations: TranslationMap
) : AbstractTranslation

@Serializable
public data class TranslationModification(
override val languageCode: LanguageCode,
override val languageName: LanguageName?,
override val default: Boolean,
override val translations: TranslationMap
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ import io.konform.validation.jsonschema.maxLength
import io.konform.validation.jsonschema.minLength

public val validateTranslation: Validation<AbstractTranslation> = Validation {
AbstractTranslation::languageCode {
matches(Regex.LanguageCode)
}

AbstractTranslation::languageName ifPresent {
minLength(2)
maxLength(30)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,50 +173,45 @@ class BridgedBeamClient : BeamClient, KoinComponent {
readOnlyError()

override suspend fun postTranslation(
spaceId: SpaceIdentifier?,
languageCode: LanguageCode,
translation: TranslationModification
): Result<Translation> =
readOnlyError()

override suspend fun postTranslation(
spaceId: SpaceIdentifier?,
languageCode: LanguageCode,
configure: suspend TranslationModificationBuilder.() -> Unit
): Result<Translation> =
readOnlyError()

override suspend fun getTranslation(spaceId: SpaceIdentifier?, languageCode: LanguageCode): Result<Translation> =
override suspend fun getTranslation(languageCode: LanguageCode): Result<Translation> =
notYetImplementedError()

override suspend fun getResolvedTranslation(
spaceId: SpaceIdentifier?,
languageCode: LanguageCode
): Result<Translation> =
override suspend fun getResolvedTranslation(languageCode: LanguageCode): Result<Translation> =
runCatching {
val translation = translationService.resolveTranslation(spaceId, languageCode, requireDto = true)
val translation = translationService.resolveTranslation(languageCode, requireDto = true)
.getOrThrow()
.dto

requireNotNull(translation)
}

override suspend fun getTranslations(spaceId: SpaceIdentifier?): Result<Translations> =
override suspend fun getTranslations(): Result<Translations> =
notYetImplementedError()

override suspend fun putTranslation(
spaceId: SpaceIdentifier?,
languageCode: LanguageCode,
translation: TranslationModification
): Result<Translation> =
notYetImplementedError()

override suspend fun putTranslation(
spaceId: SpaceIdentifier?,
languageCode: LanguageCode,
configure: suspend TranslationModificationBuilder.() -> Unit
): Result<Translation> =
notYetImplementedError()

override suspend fun deleteTranslation(spaceId: SpaceIdentifier?, languageCode: LanguageCode): Result<Unit> =
override suspend fun deleteTranslation(languageCode: LanguageCode): Result<Unit> =
readOnlyError()

override suspend fun onSpaceCreated(block: suspend (ClientWebSocketEvent<Space>) -> Unit): Result<Job> =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ class TranslationDtoConverter : DtoConverter<TranslationEntity, Translation>, Ko
override suspend fun convertToDto(entity: TranslationEntity) =
entity.run {
Translation(
space?.id?.toString(),
languageCode,
requireNotNull(languageName) { "Language name is required in DTO" },
default,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ class TranslationModificationDtoConverter : DtoConverter<TranslationEntity, Tran

override suspend fun convertToEntity(dto: TranslationModification) =
TranslationEntity {
languageCode = dto.languageCode
languageName = dto.languageName
default = dto.default
translations = dto.translations
Expand Down
Loading

0 comments on commit 3766cc5

Please sign in to comment.