Skip to content

Commit d176dc9

Browse files
authored
Merge pull request #630 from NDLANO/support-several-language-codes
Support several language codes
2 parents 07e1441 + e0a2f57 commit d176dc9

File tree

46 files changed

+189
-246
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+189
-246
lines changed

article-api/src/main/scala/no/ndla/articleapi/controller/ArticleControllerV2.scala

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import no.ndla.articleapi.validation.ContentValidator
1919
import no.ndla.articleapi.Props
2020
import no.ndla.common.ContentURIUtil.parseArticleIdAndRevision
2121
import no.ndla.common.model.api.CommaSeparatedList.*
22+
import no.ndla.language.Language
2223
import no.ndla.language.Language.AllLanguages
2324
import no.ndla.network.tapir.NoNullJsonPrinter.jsonBody
2425
import no.ndla.network.tapir.Parameters.feideHeader
@@ -147,7 +148,7 @@ trait ArticleControllerV2 {
147148
queryOrEmpty,
148149
parsedPageSize,
149150
parsedPageNo,
150-
language
151+
Language.languageOrParam(language)
151152
)
152153
.asRight
153154
}
@@ -234,7 +235,7 @@ trait ArticleControllerV2 {
234235
search(
235236
query,
236237
sort,
237-
language,
238+
Language.languageOrParam(language),
238239
license,
239240
page,
240241
pageSize,
@@ -275,7 +276,7 @@ trait ArticleControllerV2 {
275276
readService
276277
.getArticlesByIds(
277278
ids.values,
278-
language,
279+
Language.languageOrParam(language),
279280
fallback,
280281
page,
281282
pageSize,
@@ -310,7 +311,7 @@ trait ArticleControllerV2 {
310311
search(
311312
query,
312313
sort,
313-
language,
314+
Language.languageOrParam(language),
314315
license,
315316
page,
316317
pageSize,
@@ -337,10 +338,10 @@ trait ArticleControllerV2 {
337338
val (articleId, revisionQuery, feideToken, language, fallback) = params
338339
(parseArticleIdAndRevision(articleId) match {
339340
case (Failure(_), _) =>
340-
readService.getArticleBySlug(articleId, language, fallback)
341+
readService.getArticleBySlug(articleId, Language.languageOrParam(language), fallback)
341342
case (Success(articleId), inlineRevision) =>
342343
val revision = inlineRevision.orElse(revisionQuery)
343-
readService.withIdV2(articleId, language, fallback, revision, feideToken)
344+
readService.withIdV2(articleId, Language.languageOrParam(language), fallback, revision, feideToken)
344345
}).map(_.Ok())
345346
}
346347

audio-api/src/main/scala/no/ndla/audioapi/controller/AudioController.scala

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,28 +37,23 @@ import java.io.File
3737
import scala.util.{Failure, Success, Try}
3838

3939
trait AudioController {
40-
this: AudioRepository
41-
with ReadService
42-
with WriteService
43-
with AudioSearchService
44-
with SearchConverterService
45-
with ConverterService
46-
with Props
47-
with ErrorHandling
48-
with TapirController =>
40+
this: AudioRepository & ReadService & WriteService & AudioSearchService & SearchConverterService & ConverterService &
41+
Props & ErrorHandling & TapirController =>
4942
val audioApiController: AudioController
5043

51-
class AudioController() extends TapirController {
52-
import props._
53-
val maxAudioFileSizeBytes = props.MaxAudioFileSizeBytes
44+
class AudioController extends TapirController {
45+
import props.*
46+
val maxAudioFileSizeBytes: Int = props.MaxAudioFileSizeBytes
5447
override val serviceName: String = "audio"
5548
override val prefix: EndpointInput[Unit] = "audio-api" / "v1" / serviceName
5649

5750
private val queryString = query[Option[NonEmptyString]]("query")
5851
.description("Return only results with titles or tags matching the specified query.")
5952
.schema(NonEmptyString.schemaOpt)
6053
private val language =
61-
query[Option[String]]("language").description("The ISO 639-1 language code describing language.")
54+
query[Option[String]]("language")
55+
.description("The ISO 639-1 language code describing language.")
56+
.default(Some(Language.AllLanguages))
6257
private val license = query[Option[String]]("license").description("Return only audio with provided license.")
6358
private val pageNo = query[Option[Int]]("page").description("The page number of the search hits to display.")
6459
private val pageSize = query[Option[Int]]("page-size").description(
@@ -95,7 +90,7 @@ trait AudioController {
9590
private val pathAudioId = path[Long]("audio-id").description("Id of audio.")
9691
private val pathLanguage = path[String]("language").description("The ISO 639-1 language code describing language.")
9792

98-
import ErrorHelpers._
93+
import ErrorHelpers.*
9994

10095
def getSearch: ServerEndpoint[Any, Eff] = endpoint.get
10196
.summary("Find audio files")
@@ -341,7 +336,7 @@ trait AudioController {
341336
case Some(q) =>
342337
SearchSettings(
343338
query = Some(q),
344-
language = language,
339+
language = language.map(Language.languageOrParam),
345340
license = license,
346341
page = page,
347342
pageSize = pageSize,
@@ -355,7 +350,7 @@ trait AudioController {
355350
case None =>
356351
SearchSettings(
357352
query = None,
358-
language = language,
353+
language = language.map(Language.languageOrParam),
359354
license = license,
360355
page = page,
361356
pageSize = pageSize,

audio-api/src/main/scala/no/ndla/audioapi/repository/AudioRepository.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import scalikejdbc.*
2020
import scala.util.{Failure, Success, Try}
2121

2222
trait AudioRepository {
23-
this: DataSource with SeriesRepository with Props with ErrorHandling =>
23+
this: DataSource & SeriesRepository & Props & ErrorHandling =>
2424
val audioRepository: AudioRepository
2525

2626
class AudioRepository extends StrictLogging with Repository[AudioMetaInformation] {

audio-api/src/main/scala/no/ndla/audioapi/repository/SeriesRepository.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import no.ndla.database.DataSource
2323
import scala.util.{Failure, Success, Try}
2424

2525
trait SeriesRepository {
26-
this: DataSource with Props with ErrorHandling =>
26+
this: DataSource & Props & ErrorHandling =>
2727
val seriesRepository: SeriesRepository
2828

2929
class SeriesRepository extends StrictLogging with Repository[Series] {

audio-api/src/main/scala/no/ndla/audioapi/service/ReadService.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import no.ndla.common.errors.{NotFoundException, ValidationException}
1717
import scala.util.{Failure, Success, Try}
1818

1919
trait ReadService {
20-
this: AudioRepository with SeriesRepository with ConverterService with TagSearchService with SearchConverterService =>
20+
this: AudioRepository & SeriesRepository & ConverterService & TagSearchService & SearchConverterService =>
2121
val readService: ReadService
2222

2323
class ReadService {
@@ -27,7 +27,7 @@ trait ReadService {
2727
case Failure(ex) => Failure(ex)
2828
case Success(None) =>
2929
Failure(
30-
new NotFoundException(
30+
NotFoundException(
3131
s"The series with id '$seriesId' and language '${language.getOrElse("")}' was not found."
3232
)
3333
)

audio-api/src/main/scala/no/ndla/audioapi/service/TranscriptionService.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ trait TranscriptionService {
3636
getVideoTranscription(videoId, language) match {
3737
case Success(TranscriptionComplete(_)) =>
3838
logger.info(s"Transcription already completed for videoId: $videoId")
39-
return Failure(new JobAlreadyFoundException(s"Transcription already completed for videoId: $videoId"))
39+
return Failure(JobAlreadyFoundException(s"Transcription already completed for videoId: $videoId"))
4040
case Success(TranscriptionNonComplete(TranscriptionJobStatus.IN_PROGRESS)) =>
4141
logger.info(s"Transcription already in progress for videoId: $videoId")
42-
return Failure(new JobAlreadyFoundException(s"Transcription already in progress for videoId: $videoId"))
42+
return Failure(JobAlreadyFoundException(s"Transcription already in progress for videoId: $videoId"))
4343
case _ =>
4444
logger.info(s"No existing transcription job for videoId: $videoId")
4545
}
@@ -93,7 +93,7 @@ trait TranscriptionService {
9393
val transcriptionJobStatus = transcriptionJob.transcriptionJobStatus()
9494

9595
if (transcriptionJobStatus == "COMPLETED") {
96-
val transcribeUri = s"transcription/$language/${videoId}.vtt"
96+
val transcribeUri = s"transcription/$language/$videoId.vtt"
9797

9898
getObjectFromS3(transcribeUri).map(TranscriptionComplete(_))
9999
} else {
@@ -112,10 +112,10 @@ trait TranscriptionService {
112112
getAudioTranscription(audioId, language) match {
113113
case Success(Right(_)) =>
114114
logger.info(s"Transcription already completed for audio: $audioName")
115-
return Failure(new JobAlreadyFoundException(s"Transcription already completed for audio: $audioName"))
115+
return Failure(JobAlreadyFoundException(s"Transcription already completed for audio: $audioName"))
116116
case Success(Left("IN_PROGRESS")) =>
117117
logger.info(s"Transcription already in progress for videoId: $audioName")
118-
return Failure(new JobAlreadyFoundException(s"Transcription already in progress for audio: $audioName"))
118+
return Failure(JobAlreadyFoundException(s"Transcription already in progress for audio: $audioName"))
119119
case _ =>
120120
logger.info(s"No existing transcription job for audio name: $audioName")
121121
}
@@ -151,7 +151,7 @@ trait TranscriptionService {
151151
val transcriptionJobStatus = transcriptionJob.transcriptionJobStatus().toString
152152

153153
if (transcriptionJobStatus == "COMPLETED") {
154-
val transcribeUri = s"audio-transcription/$language/${audioId}"
154+
val transcribeUri = s"audio-transcription/$language/$audioId"
155155

156156
getObjectFromS3(transcribeUri).map(Right(_))
157157
} else {
@@ -180,7 +180,7 @@ trait TranscriptionService {
180180
case Failure(ex) => throw new RuntimeException(s"Failed to download video: $ex")
181181
}
182182

183-
val audioFile = new File(s"/tmp/audio_${videoId}.mp3")
183+
val audioFile = new File(s"/tmp/audio_$videoId.mp3")
184184

185185
val audioAttributes = new AudioAttributes()
186186
audioAttributes.setCodec("libmp3lame")
@@ -221,7 +221,7 @@ trait TranscriptionService {
221221
}
222222

223223
def getAudioExtractionStatus(videoId: String, language: String): Try[Unit] = {
224-
s3TranscribeClient.getObject(s"audio-extraction/$language/${videoId}.mp3") match {
224+
s3TranscribeClient.getObject(s"audio-extraction/$language/$videoId.mp3") match {
225225
case Success(_) => Success(())
226226
case Failure(exception) => Failure(exception)
227227
}

audio-api/src/main/scala/no/ndla/audioapi/service/WriteService.scala

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,16 @@ import java.lang.Math.max
2727
import scala.util.{Failure, Random, Success, Try}
2828

2929
trait WriteService {
30-
this: ConverterService
31-
with ValidationService
32-
with AudioRepository
33-
with SeriesRepository
34-
with AudioIndexService
35-
with SeriesIndexService
36-
with TagIndexService
37-
with NdlaS3Client
38-
with ReadService
39-
with Clock =>
30+
this: ConverterService & ValidationService & AudioRepository & SeriesRepository & AudioIndexService &
31+
SeriesIndexService & TagIndexService & NdlaS3Client & ReadService & Clock =>
4032
val writeService: WriteService
4133

4234
class WriteService extends StrictLogging {
4335

4436
def updateSeries(id: Long, toUpdateSeries: api.NewSeriesDTO): Try[api.SeriesDTO] = {
4537
seriesRepository.withId(id) match {
4638
case Failure(ex) => Failure(ex)
47-
case Success(None) => Failure(new NotFoundException(s"Could not find series to update with id: '$id'"))
39+
case Success(None) => Failure(NotFoundException(s"Could not find series to update with id: '$id'"))
4840
case Success(Some(existingSeries)) =>
4941
val merged = converterService.updateSeries(existingSeries, toUpdateSeries)
5042
val oldEpisodesIds = existingSeries.episodes.traverse(_.flatMap(_.id)).flatten.toSet
@@ -85,7 +77,7 @@ trait WriteService {
8577

8678
}
8779

88-
def updateSeriesForEpisodes(seriesId: Option[Long], episodeIds: Seq[Long]): Try[_] =
80+
def updateSeriesForEpisodes(seriesId: Option[Long], episodeIds: Seq[Long]): Try[?] =
8981
episodeIds.traverse(id =>
9082
for {
9183
_ <- audioRepository.setSeriesId(
@@ -95,7 +87,7 @@ trait WriteService {
9587
episode <- audioRepository.withId(id) match {
9688
case Some(ep) => Success(ep)
9789
case None =>
98-
Failure(new NotFoundException(s"Could not find episode with id '$id' when updating series connection."))
90+
Failure(NotFoundException(s"Could not find episode with id '$id' when updating series connection."))
9991
}
10092
reindexed <- audioIndexService.indexDocument(episode)
10193
} yield reindexed
@@ -105,7 +97,7 @@ trait WriteService {
10597
seriesRepository.withId(seriesId) match {
10698
case Failure(ex) => Failure(ex)
10799
case Success(None) =>
108-
Failure(new NotFoundException(s"Series with id $seriesId was not found, and could not be deleted."))
100+
Failure(NotFoundException(s"Series with id $seriesId was not found, and could not be deleted."))
109101
case Success(Some(existingSeries)) =>
110102
val episodes = existingSeries.episodes.getOrElse(Seq.empty)
111103
freeEpisodes(episodes) match {
@@ -114,7 +106,7 @@ trait WriteService {
114106
seriesRepository.deleteWithId(seriesId) match {
115107
case Success(numRows) if numRows > 0 => seriesIndexService.deleteDocument(seriesId)
116108
case Success(_) =>
117-
Failure(new NotFoundException(s"Could not find series to delete with id: '$seriesId'"))
109+
Failure(NotFoundException(s"Could not find series to delete with id: '$seriesId'"))
118110
case Failure(ex) => Failure(ex)
119111
}
120112
}
@@ -159,9 +151,9 @@ trait WriteService {
159151
}
160152

161153
case Some(_) =>
162-
Failure(new NotFoundException(s"Audio with id $audioId does not exist in language '$language'."))
154+
Failure(NotFoundException(s"Audio with id $audioId does not exist in language '$language'."))
163155
case None =>
164-
Failure(new NotFoundException(s"Audio with id $audioId was not found, and could not be deleted."))
156+
Failure(NotFoundException(s"Audio with id $audioId was not found, and could not be deleted."))
165157
}
166158

167159
def deleteSeriesLanguageVersion(seriesId: Long, language: String): Try[Option[api.SeriesDTO]] = {
@@ -182,9 +174,9 @@ trait WriteService {
182174
} yield result
183175
}
184176
case Success(Some(_)) =>
185-
Failure(new NotFoundException(s"Series with id $seriesId does not exist in language '$language'."))
177+
Failure(NotFoundException(s"Series with id $seriesId does not exist in language '$language'."))
186178
case Success(None) =>
187-
Failure(new NotFoundException(s"Series with id $seriesId was not found, and could not be deleted."))
179+
Failure(NotFoundException(s"Series with id $seriesId was not found, and could not be deleted."))
188180
case Failure(ex) => Failure(ex)
189181
}
190182
}
@@ -255,7 +247,7 @@ trait WriteService {
255247

256248
if (metaDeleted < 1) {
257249
Failure(
258-
new NotFoundException(s"Metadata for audio with id $audioId was not found, and could not be deleted.")
250+
NotFoundException(s"Metadata for audio with id $audioId was not found, and could not be deleted.")
259251
)
260252
} else if (filesDeleted.exists(_.isFailure)) {
261253
val exceptions = filesDeleted.collect { case Failure(ex) => ex }
@@ -268,7 +260,7 @@ trait WriteService {
268260
}
269261
}
270262

271-
case None => Failure(new NotFoundException(s"Audio with id $audioId was not found, and could not be deleted."))
263+
case None => Failure(NotFoundException(s"Audio with id $audioId was not found, and could not be deleted."))
272264
}
273265
}
274266

audio-api/src/main/scala/no/ndla/audioapi/service/search/AudioIndexService.scala

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,12 @@ import no.ndla.search.Elastic4sClient
2424
import scala.util.{Failure, Try}
2525

2626
trait AudioIndexService {
27-
this: Elastic4sClient
28-
with SearchConverterService
29-
with IndexService
30-
with SeriesIndexService
31-
with AudioRepository
32-
with Props =>
27+
this: Elastic4sClient & SearchConverterService & IndexService & SeriesIndexService & AudioRepository & Props =>
3328

3429
val audioIndexService: AudioIndexService
3530

3631
class AudioIndexService extends StrictLogging with IndexService[AudioMetaInformation, SearchableAudioInformation] {
37-
import props._
32+
import props.*
3833
override val documentType: String = SearchDocument
3934
override val searchIndex: String = SearchIndex
4035
override val repository: AudioRepository = audioRepository

audio-api/src/main/scala/no/ndla/audioapi/service/search/AudioSearchService.scala

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,11 @@ import scala.concurrent.Future
2727
import scala.util.{Failure, Success, Try}
2828

2929
trait AudioSearchService {
30-
this: Elastic4sClient
31-
with AudioIndexService
32-
with SearchConverterService
33-
with SearchService
34-
with Props
35-
with ErrorHandling =>
30+
this: Elastic4sClient & AudioIndexService & SearchConverterService & SearchService & Props & ErrorHandling =>
3631
val audioSearchService: AudioSearchService
3732

3833
class AudioSearchService extends StrictLogging with SearchService[api.AudioSummaryDTO] {
39-
import props._
34+
import props.*
4035

4136
override val searchIndex: String = SearchIndex
4237

audio-api/src/main/scala/no/ndla/audioapi/service/search/SearchConverterService.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@
88

99
package no.ndla.audioapi.service.search
1010

11-
import cats.implicits._
11+
import cats.implicits.*
1212
import com.sksamuel.elastic4s.requests.searches.SearchHit
1313
import com.typesafe.scalalogging.StrictLogging
1414
import no.ndla.audioapi.Props
1515
import no.ndla.audioapi.model.api.TitleDTO
1616
import no.ndla.audioapi.model.domain.{AudioMetaInformation, SearchResult, SearchableTag}
17-
import no.ndla.audioapi.model.search._
17+
import no.ndla.audioapi.model.search.*
1818
import no.ndla.audioapi.model.{api, domain}
1919
import no.ndla.audioapi.service.ConverterService
20-
import no.ndla.common.model.{domain => common}
20+
import no.ndla.common.model.domain as common
2121
import no.ndla.language.Language.{findByLanguageOrBestEffort, getSupportedLanguages}
2222
import no.ndla.search.SearchLanguage
2323
import no.ndla.search.model.{LanguageValue, SearchableLanguageList, SearchableLanguageValues}
@@ -181,7 +181,7 @@ trait SearchConverterService {
181181
.lastOption
182182
}
183183

184-
val highlightKeys: Option[Map[String, _]] = Option(result.highlight)
184+
val highlightKeys: Option[Map[String, ?]] = Option(result.highlight)
185185
val matchLanguage = keyToLanguage(highlightKeys.getOrElse(Map()).keys)
186186

187187
matchLanguage match {

0 commit comments

Comments
 (0)