From 3562b6f06826d63b553c815a5bb0945726641ad6 Mon Sep 17 00:00:00 2001 From: Hugo Pezziardi Date: Wed, 24 Jan 2024 14:36:46 +0100 Subject: [PATCH 1/3] :globe_with_meridians: (GEK): Add localization for MelodyView --- .../Resources/Localizable.xcstrings | 72 +++++++++++++++++++ .../Specialized/Melody/MelodyView+l10n.swift | 21 ++++++ 2 files changed, 93 insertions(+) create mode 100644 Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView+l10n.swift diff --git a/Modules/GameEngineKit/Resources/Localizable.xcstrings b/Modules/GameEngineKit/Resources/Localizable.xcstrings index fa3426881d..6469272abe 100644 --- a/Modules/GameEngineKit/Resources/Localizable.xcstrings +++ b/Modules/GameEngineKit/Resources/Localizable.xcstrings @@ -126,6 +126,78 @@ } } } + }, + "lekaapp.melody_view.keyboard_full" : { + "comment" : "MelodyView keyboard full keyboard label", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Full keyboard" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clavier entier" + } + } + } + }, + "lekaapp.melody_view.keyboard_partial" : { + "comment" : "MelodyView partial keyboard label", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Partial keyboard" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clavier partiel" + } + } + } + }, + "lekaapp.melody_view.play_button_label" : { + "comment" : "MelodyView play button label", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Play" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jouer" + } + } + } + }, + "lekaapp.melody_view.song_selector_title" : { + "comment" : "MelodyView music selection title", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Music selection" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sélection de la musique" + } + } + } } }, "version" : "1.0" diff --git a/Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView+l10n.swift b/Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView+l10n.swift new file mode 100644 index 0000000000..06caae9793 --- /dev/null +++ b/Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView+l10n.swift @@ -0,0 +1,21 @@ +// Leka - iOS Monorepo +// Copyright APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +import LocalizationKit + +// swiftlint:disable line_length + +extension l10n { + enum MelodyView { + static let musicSelectionTitle = LocalizedString("lekaapp.melody_view.song_selector_title", value: "Music selection", comment: "MelodyView music selection title") + + static let playButtonLabel = LocalizedString("lekaapp.melody_view.play_button_label", value: "Play", comment: "MelodyView play button label") + + static let partialKeyboardLabel = LocalizedString("lekaapp.melody_view.keyboard_partial", value: "Partial keyboard", comment: "MelodyView partial keyboard label") + + static let fullKeyboardLabel = LocalizedString("lekaapp.melody_view.keyboard_full", value: "Full keyboard", comment: "MelodyView keyboard full keyboard label") + } +} + +// swiftlint:enable line_length From 046f9c2c1e4840c6603b1d667ffc01693359e2cc Mon Sep 17 00:00:00 2001 From: Hugo Pezziardi Date: Wed, 24 Jan 2024 14:38:11 +0100 Subject: [PATCH 2/3] :recycle: (GEK): Use l10n in Melody views --- .../Melody/MelodyView+KeyboardModeView.swift | 18 +++++------------ .../Melody/MelodyView+LauncherView.swift | 20 +++++-------------- .../Melody/MelodyView+SongSelectorView.swift | 16 ++++----------- .../Specialized/Melody/MelodyView.swift | 17 +++------------- 4 files changed, 17 insertions(+), 54 deletions(-) diff --git a/Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView+KeyboardModeView.swift b/Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView+KeyboardModeView.swift index cb11190bcf..a335ab6fe6 100644 --- a/Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView+KeyboardModeView.swift +++ b/Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView+KeyboardModeView.swift @@ -4,15 +4,15 @@ import ContentKit import DesignKit +import LocalizationKit import SwiftUI extension MelodyView { struct KeyboardModeView: View { // MARK: Lifecycle - init(keyboard: Binding, instructions: MidiRecordingPlayer.Payload.Instructions) { + init(keyboard: Binding) { self._keyboard = keyboard - self.instructions = instructions } // MARK: Internal @@ -23,7 +23,7 @@ extension MelodyView { GameEngineKitAsset.Exercises.Melody.iconKeyboardPartial.swiftUIImage .resizable() .scaledToFit() - Text(self.instructions.textKeyboardPartial) + Text(l10n.MelodyView.partialKeyboardLabel) .foregroundStyle(self.keyboard == .partial ? .black : .gray.opacity(0.4)) } .onTapGesture { @@ -36,7 +36,7 @@ extension MelodyView { GameEngineKitAsset.Exercises.Melody.iconKeyboardFull.swiftUIImage .resizable() .scaledToFit() - Text(self.instructions.textKeyboardFull) + Text(l10n.MelodyView.fullKeyboardLabel) .foregroundStyle(self.keyboard == .full ? .black : .gray.opacity(0.4)) } .onTapGesture { @@ -52,7 +52,6 @@ extension MelodyView { // MARK: Private @Binding private var keyboard: KeyboardType - private let instructions: MidiRecordingPlayer.Payload.Instructions } } @@ -63,15 +62,8 @@ extension MelodyView { MidiRecording(.twinkleTwinkleLittleStar), MidiRecording(.underTheMoonlight), ] - let instructions = MidiRecordingPlayer.Payload.Instructions( - textMusicSelection: "Sélection de la musique", - textButtonPlay: "Jouer", - textKeyboardPartial: "Clavier partiel", - textKeyboardFull: "Clavier entier" - ) return MelodyView.KeyboardModeView( - keyboard: .constant(.partial), - instructions: instructions + keyboard: .constant(.partial) ) } diff --git a/Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView+LauncherView.swift b/Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView+LauncherView.swift index 2e4fff0309..197d8bedf9 100644 --- a/Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView+LauncherView.swift +++ b/Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView+LauncherView.swift @@ -3,6 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 import ContentKit +import LocalizationKit import SwiftUI extension MelodyView { @@ -11,7 +12,6 @@ extension MelodyView { @Binding var mode: Stage @Binding var keyboard: KeyboardType let songs: [MidiRecording] - let instructions: MidiRecordingPlayer.Payload.Instructions var body: some View { VStack(spacing: 100) { @@ -22,12 +22,9 @@ extension MelodyView { .padding(.trailing, 50) VStack(spacing: 0) { - KeyboardModeView(keyboard: self.$keyboard, instructions: self.instructions) + KeyboardModeView(keyboard: self.$keyboard) - SongSelectorView( - songs: self.songs, selectedMidiRecording: self.$selectedSong, - textMusicSelection: self.instructions.textMusicSelection - ) + SongSelectorView(songs: self.songs, selectedMidiRecording: self.$selectedSong) } } .padding(.horizontal, 100) @@ -35,7 +32,7 @@ extension MelodyView { Button { self.mode = .selectionConfirmed } label: { - ButtonLabel(self.instructions.textButtonPlay, color: .cyan) + ButtonLabel(String(l10n.MelodyView.playButtonLabel.characters), color: .cyan) } } } @@ -51,18 +48,11 @@ extension MelodyView { MidiRecording(.ohTheCrocodiles), MidiRecording(.happyBirthday), ] - let instructions = MidiRecordingPlayer.Payload.Instructions( - textMusicSelection: "Sélection de la musique", - textButtonPlay: "Jouer", - textKeyboardPartial: "Clavier partiel", - textKeyboardFull: "Clavier entier" - ) return MelodyView.LauncherView( selectedSong: .constant(MidiRecording(.underTheMoonlight)), mode: .constant(.waitingForSelection), keyboard: .constant(.partial), - songs: songs, - instructions: instructions + songs: songs ) } diff --git a/Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView+SongSelectorView.swift b/Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView+SongSelectorView.swift index 6bb01f9614..bf497d7da0 100644 --- a/Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView+SongSelectorView.swift +++ b/Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView+SongSelectorView.swift @@ -4,23 +4,22 @@ import ContentKit import DesignKit +import LocalizationKit import SwiftUI extension MelodyView { struct SongSelectorView: View { // MARK: Lifecycle - init(songs: [MidiRecording], selectedMidiRecording: Binding, textMusicSelection: String) { + init(songs: [MidiRecording], selectedMidiRecording: Binding) { self.songs = songs self._selectedMidiRecording = selectedMidiRecording - self.textMusicSelection = textMusicSelection } // MARK: Internal @Binding var selectedMidiRecording: MidiRecording let songs: [MidiRecording] - let textMusicSelection: String let columns = [ GridItem(.flexible()), @@ -29,7 +28,7 @@ extension MelodyView { var body: some View { VStack(alignment: .leading) { - Text(self.textMusicSelection) + Text(l10n.MelodyView.musicSelectionTitle) // TODO: (@ui/ux) - Design System - replace with Leka font .font(.headline) @@ -68,16 +67,9 @@ extension MelodyView { MidiRecording(.twinkleTwinkleLittleStar), MidiRecording(.underTheMoonlight), ] - let instructions = MidiRecordingPlayer.Payload.Instructions( - textMusicSelection: "Sélection de la musique", - textButtonPlay: "Jouer", - textKeyboardPartial: "Clavier partiel", - textKeyboardFull: "Clavier entier" - ) return MelodyView.SongSelectorView( songs: songs, - selectedMidiRecording: .constant(MidiRecording(.underTheMoonlight)), - textMusicSelection: instructions.textMusicSelection + selectedMidiRecording: .constant(MidiRecording(.underTheMoonlight)) ) } diff --git a/Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView.swift b/Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView.swift index f5dd90e5c6..c309e5e4ce 100644 --- a/Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView.swift +++ b/Modules/GameEngineKit/Sources/_NewSystem/Exercises/Specialized/Melody/MelodyView.swift @@ -9,8 +9,7 @@ import SwiftUI public struct MelodyView: View { // MARK: Lifecycle - init(instructions: MidiRecordingPlayer.Payload.Instructions, instrument: MIDIInstrument, songs: [MidiRecording]) { - self.instructions = instructions + init(instrument: MIDIInstrument, songs: [MidiRecording]) { self.instrument = instrument self.songs = songs self.selectedSong = songs.first! @@ -27,7 +26,6 @@ public struct MelodyView: View { fatalError("Instrument or song not found") } - self.instructions = payload.instructions self.instrument = instrument self.songs = payload.songs self.selectedSong = self.songs.first! @@ -41,8 +39,7 @@ public struct MelodyView: View { switch self.mode { case .waitingForSelection: LauncherView( - selectedSong: self.$selectedSong, mode: self.$mode, keyboard: self.$keyboard, songs: self.songs, - instructions: self.instructions + selectedSong: self.$selectedSong, mode: self.$mode, keyboard: self.$keyboard, songs: self.songs ) case .selectionConfirmed: switch self.instrument { @@ -69,7 +66,6 @@ public struct MelodyView: View { } let data: ExerciseSharedData? - let instructions: MidiRecordingPlayer.Payload.Instructions let instrument: MIDIInstrument let songs: [MidiRecording] @@ -81,12 +77,5 @@ public struct MelodyView: View { } #Preview { - let instructions = MidiRecordingPlayer.Payload.Instructions( - textMusicSelection: "Sélection de la musique", - textButtonPlay: "Jouer", - textKeyboardPartial: "Clavier partiel", - textKeyboardFull: "Clavier entier" - ) - - return MelodyView(instructions: instructions, instrument: .xylophone, songs: [MidiRecording(.underTheMoonlight)]) + MelodyView(instrument: .xylophone, songs: [MidiRecording(.underTheMoonlight)]) } From a48061d635986daed51580cd3d19eb767bf530ef Mon Sep 17 00:00:00 2001 From: Hugo Pezziardi Date: Wed, 24 Jan 2024 14:38:43 +0100 Subject: [PATCH 3/3] :fire: (ContentKit): Remove instructions payload for MIDIRecordingPlayer --- .../activities/activity-melody.yml | 5 --- .../Exercice+MidiRecordingPlayer.swift | 45 ------------------- 2 files changed, 50 deletions(-) diff --git a/Apps/LekaActivityUIExplorer/Resources/GEKNewSystem/activities/activity-melody.yml b/Apps/LekaActivityUIExplorer/Resources/GEKNewSystem/activities/activity-melody.yml index 402792f8eb..3edf5ff0bf 100644 --- a/Apps/LekaActivityUIExplorer/Resources/GEKNewSystem/activities/activity-melody.yml +++ b/Apps/LekaActivityUIExplorer/Resources/GEKNewSystem/activities/activity-melody.yml @@ -11,11 +11,6 @@ sequence: - instructions: Joue les notes de la même couleur que Leka interface: melody payload: - instructions: - text_music_selection: Sélection de la musique - text_button_play: Jouer - text_keyboard_partial: Clavier partiel - text_keyboard_full: Clavier entier instrument: xylophone songs: - underTheMoonlight diff --git a/Modules/ContentKit/Sources/Exercise/Exercice+MidiRecordingPlayer.swift b/Modules/ContentKit/Sources/Exercise/Exercice+MidiRecordingPlayer.swift index abc2855b8a..6a6225595e 100644 --- a/Modules/ContentKit/Sources/Exercise/Exercice+MidiRecordingPlayer.swift +++ b/Modules/ContentKit/Sources/Exercise/Exercice+MidiRecordingPlayer.swift @@ -2,14 +2,12 @@ // Copyright APF France handicap // SPDX-License-Identifier: Apache-2.0 -// swiftlint:disable nesting public enum MidiRecordingPlayer { public struct Payload: Codable { // MARK: Lifecycle public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) - self.instructions = try container.decode(Instructions.self, forKey: .instructions) self.instrument = try container.decode(String.self, forKey: .instrument) let midiRecordingSongs = try container.decode([MidiRecording.Song].self, forKey: .songs) @@ -18,57 +16,14 @@ public enum MidiRecordingPlayer { // MARK: Public - public struct Instructions: Codable { - // MARK: Lifecycle - - public init( - textMusicSelection: String, textButtonPlay: String, textKeyboardPartial: String, - textKeyboardFull: String - ) { - self.textMusicSelection = textMusicSelection - self.textButtonPlay = textButtonPlay - self.textKeyboardPartial = textKeyboardPartial - self.textKeyboardFull = textKeyboardFull - } - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - self.textMusicSelection = try container.decode(String.self, forKey: .textMusicSelection) - self.textButtonPlay = try container.decode(String.self, forKey: .textButtonPlay) - self.textKeyboardPartial = try container.decode(String.self, forKey: .textKeyboardPartial) - self.textKeyboardFull = try container.decode(String.self, forKey: .textKeyboardFull) - } - - // MARK: Public - - public let textMusicSelection: String - public let textButtonPlay: String - public let textKeyboardPartial: String - public let textKeyboardFull: String - - // MARK: Internal - - enum CodingKeys: String, CodingKey { - case textMusicSelection = "text_music_selection" - case textButtonPlay = "text_button_play" - case textKeyboardPartial = "text_keyboard_partial" - case textKeyboardFull = "text_keyboard_full" - } - } - - public let instructions: Instructions public let instrument: String public let songs: [MidiRecording] // MARK: Internal enum CodingKeys: String, CodingKey { - case instructions case instrument case songs } } } - -// swiftlint:enable nesting