diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml index bc768f2f..9a3def24 100644 --- a/composeApp/src/commonMain/composeResources/values/strings.xml +++ b/composeApp/src/commonMain/composeResources/values/strings.xml @@ -21,4 +21,255 @@ "XML file ... is not valid. Check the file content." --> Mantra + Add a dialect the group can translate into + Add artifact to library + Add artifact to the group library + Add chapter + Add dialect + Add to group + Add translation + After this there is no turning back. + All broadcasts are queued so that we can manage data usage on metered connections. + Any amount + ARTICLE + Artifact detail + As long as you control your keys there can be no dispute about who YOU actually is. + Back + Be sure to keep this nsec safe. + Be the first to comment. + Bio + Block user + Cancel + Change account + Chapter detail + Chapter name + Chapter translation + Chapters + Choose who to chat with + Close + Copy URL + Country + Create chat + Create new chat + Create profile + Create project + Create the #admins group + Creating new chat. + Currently no contacts. Please search and chat with a few people. + Currently no messages have been shared.\nBreak the ice. + Delete group + Details + Dialect name + Dialects + Direct message detail + Direct message functionality will be here. + Direct message via npub + Don't sign + Download + Edit profile + eg. Chapter 1 — The Beginning + eg. First Edition + eg. https://harper.com/2-kill-Bird + eg. Lesotho + eg. Sesotho + eg. st + eg. To Kill a Mocking Bird + end this + ENDED + Enter the name you want to use for your group + Enter the name you want to use for your profile + Enter the nsec or npub (read only) that you want to sign in as + Enter the translation for this chunk + Events are indexed so that we can deliver a premium local first experience. + Everything else + Everything is cryptographical sound. Just announcing your profile to the world. + Everything is cryptographical sound. Just indexing your profile on the device. + Everything is cryptographical sound. Just need to queue your profile and announce it to the world. + Expired + ✗ Failed + follow + follow back + functionality coming soon. + Has not taken part yet + How many admins have to approve a change? + How many members will it take to sign? + If you are new to Torch or just want to create a fresh profile + Initial version label + Input npub... or nip05 + Introduce yourself + Invite + Invite a friend + Invite new member + It is cryptographical secure, and decentralized, putting you in total control of your digital profile + Just you for now + Keep the feed alive. + Key + Key package management + Language + Learn more + Leave group + Library + Lightning invoice + LIVE + Live stream + Loading + Loading article... + Loading author information + Loading author information... + loading information... + Loading note... + Loading stream... + Lock prompt coming soon. + Malformed note + Mantra + Members + members + Name + Name (eg. Alan Turing) + Name (eg. Group Discussions) + Name of artifact + Network relays + New chat + Next + No artifacts exists in this groups library. + No chapters. + No chapters yet. + No chat message relays were found for this user. + No chunks. + No dialects have been defined in this group yet. Add one from the group's detail screen first. + No dialects have been defined in this group. + No events were found + No messages. Go to a profile and send them a message. + No one selected yet + No one to add yet. + No projects exists in this group. + No translations yet. + No versions. + Not now + Nothing was created and no key exists. It is safe to run it again. + nsec, npub, nip-05 (static address) + Open chat + Original + Original text + Original text (markdown) + ✓ Paid + Paste the chapter's markdown. Blank lines separate paragraphs into chunks. + Pay + Pay now + Post + post functionality coming soon. + Private to you + Profile + Profile is ready + Profile keys + Profiles + Projects + Proposals + Propose + Propose artifact + Propose chapter + Propose dialect + Propose translation + Publish new key package + Re-broadcast + Read to the end of the list to sign. + Ready to sign + Recents + Reindex events + reposted + Review + Review and confirm + Review and contribute + Review and join + Say what now? + Search + Search for people and chat with them first — everyone you know locally shows up here. + Search hashtags + Search member functionality + Search message functionality will be here. + See how deep the rabbit hole goes + Select a wallet + Send message + Share profile + Shared key + Sign + Sign in + Sign in to nsec + Sign in to Torch via nsec, or remote signer + Sign in with an npub + Sign out + Sign with the group's key + Signed their part + Skip for now + Something went wrong + Something went wrong and we were unable to sign in to your provided profile. Please try again later. + Something went wrong and we were unable to sign you up. Please try again later. + Something went wrong and we were unable to write a new note. Please try again later. + Source dialect + Start + Start a group chat + Start chat + Start chat via npub or nip05 + Start key ceremony + Startup error + Taking part with these members + Tap to load + Tell friends to join you so your feed stays lively and fresh. + The above will be your new note. + The above will be your profile. + The ceremony was abandoned. + The group can hold one key together, split so that no single member holds it. Signing with it takes a quorum. + The group has a shared key. + This artifact has no version for a translation to be of. + This artifact has no version for a chapter to attach to. + This chapter has no chunks. + This decides who can change the group later. You can't switch afterwards. + This group has no shared key, so it cannot sign them in. + This group has not been asked to sign anything yet. + This is fixed once the ceremony runs. Changing it later means generating a new key. + This is the last thing the ceremony needs from you. + This will be shown when people open the chat for more details. + This will be shown when people open your profile. + This will be the display name for this chat room. + This will be the display name for your profile and also important for search. + This will give you read only access to the profile. + This will give you write access to the profile. + Torch will be broadcast what you publish to a distributed set of relays so that it's decentralized. + Translate chunk + Translate into which dialect? + Translated text + Translation + Translation detail + Translations + Transmit note + Trending notes functionality coming soon. In the meantime search for what you are looking for. + Try again + Type out what you would like to publish + Unfollow + Unsupported event kind + Untitled article + Url + Version + Versions + View and accept invites you may have received to stay connected with others. + View invites + Waiting for you + Waiting for your signature + We are looking for your profile on as many relays as possible. Nostr aims to be decentralized by distributing data to multiple nodse. + We are searching the internet to find your profile and complete sign in. + We couldn't find the local profile. Please try again later. + We couldn't find your nostr event. Please try again later. + What's your comment on the below + What's your reply to the above + What should people know about you? + What vibrations do you want to send out? + What will be discussed in this chat room. + Who will you be passing the aux to? + You + You and 1 other + You are about to create a NOSTR profile. + You can still carry on and invite people later. + You will be in full control of this profile. If you would like to use it for the long term please remember to backup the profile/keys. + Your profile is almost ready... just getting it's first cryptographic signature together. + Your share of it is on this device only. Your wallet backup restores it — nobody else's share can. diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ActiveProfileScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ActiveProfileScreen.kt index 43b167fc..5157d5a8 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ActiveProfileScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ActiveProfileScreen.kt @@ -52,6 +52,18 @@ import press.mantra.compose.ui.view.state.ActiveProfileUIState import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.change_account +import mantra.composeapp.generated.resources.edit_profile +import mantra.composeapp.generated.resources.key_package_management +import mantra.composeapp.generated.resources.network_relays +import mantra.composeapp.generated.resources.profile +import mantra.composeapp.generated.resources.profile_keys +import mantra.composeapp.generated.resources.share_profile +import mantra.composeapp.generated.resources.sign_out +import mantra.composeapp.generated.resources.something_went_wrong +import mantra.composeapp.generated.resources.we_couldn_t_find_the_local_profile_please @OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class) @Composable @@ -80,7 +92,7 @@ fun ActiveProfileScreen( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { - Text("Something went wrong") + Text(stringResource(Res.string.something_went_wrong)) } } is ActiveProfileUIState.Loaded -> { @@ -89,7 +101,7 @@ fun ActiveProfileScreen( TopAppBar( title = { Text( - text = "Profile" + text = stringResource(Res.string.profile) ) }, navigationIcon = { @@ -177,7 +189,7 @@ fun ActiveProfileScreen( ) Text( - "Edit profile" + stringResource(Res.string.edit_profile) ) } @@ -204,7 +216,7 @@ fun ActiveProfileScreen( modifier = Modifier.width(MaterialTheme.spacing.space125) ) Text( - "Share profile" + stringResource(Res.string.share_profile) ) } @@ -236,7 +248,7 @@ fun ActiveProfileScreen( ) Text( - "Key package management" + stringResource(Res.string.key_package_management) ) } } @@ -261,7 +273,7 @@ fun ActiveProfileScreen( ) Text( - "Change account" + stringResource(Res.string.change_account) ) } } @@ -285,7 +297,7 @@ fun ActiveProfileScreen( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Profile keys") + Text(stringResource(Res.string.profile_keys)) } } @@ -308,7 +320,7 @@ fun ActiveProfileScreen( ) Text( - "Network relays" + stringResource(Res.string.network_relays) ) } } @@ -331,7 +343,7 @@ fun ActiveProfileScreen( ) Text( - "Sign out" + stringResource(Res.string.sign_out) ) } } @@ -352,7 +364,7 @@ fun ActiveProfileScreen( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { - Text("We couldn't find the local profile. Please try again later.") + Text(stringResource(Res.string.we_couldn_t_find_the_local_profile_please)) } } } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddArtifactScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddArtifactScreen.kt index dfe07bd9..c029fb2c 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddArtifactScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddArtifactScreen.kt @@ -69,6 +69,20 @@ import press.mantra.compose.ui.composable.navigation.routes.ImplementationPendin import press.mantra.compose.ui.view.model.AddArtifactViewModel import press.mantra.compose.ui.view.state.AddArtifactUIState import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.add_artifact_to_the_group_library +import mantra.composeapp.generated.resources.direct_message_detail +import mantra.composeapp.generated.resources.direct_message_functionality_will_be_here +import mantra.composeapp.generated.resources.eg_first_edition +import mantra.composeapp.generated.resources.eg_https_harper_com_2_kill_bird +import mantra.composeapp.generated.resources.eg_to_kill_a_mocking_bird +import mantra.composeapp.generated.resources.initial_version_label +import mantra.composeapp.generated.resources.name_of_artifact +import mantra.composeapp.generated.resources.no_dialects_have_been_defined_in_this_group +import mantra.composeapp.generated.resources.propose_artifact +import mantra.composeapp.generated.resources.source_dialect +import mantra.composeapp.generated.resources.url @OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class) @Composable @@ -205,7 +219,7 @@ fun AddArtifactScreen( Icons.Default.Add, contentDescription = "Propose artifact" ) - Text("Propose artifact") + Text(stringResource(Res.string.propose_artifact)) } } ) @@ -220,7 +234,7 @@ fun AddArtifactScreen( verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.space125), horizontalAlignment = Alignment.CenterHorizontally ) { - Text("Add artifact to the group library") + Text(stringResource(Res.string.add_artifact_to_the_group_library)) if (!addArtifactUIState.canSign) { Text( @@ -248,12 +262,12 @@ fun AddArtifactScreen( }, label = { Text( - text = "Name of artifact" + text = stringResource(Res.string.name_of_artifact) ) }, placeholder = { Text( - text = "eg. To Kill a Mocking Bird" + text = stringResource(Res.string.eg_to_kill_a_mocking_bird) ) }, ) @@ -275,12 +289,12 @@ fun AddArtifactScreen( }, label = { Text( - text = "Url" + text = stringResource(Res.string.url) ) }, placeholder = { Text( - text = "eg. https://harper.com/2-kill-Bird" + text = stringResource(Res.string.eg_https_harper_com_2_kill_bird) ) }, ) @@ -302,21 +316,21 @@ fun AddArtifactScreen( }, label = { Text( - text = "Initial version label" + text = stringResource(Res.string.initial_version_label) ) }, placeholder = { Text( - text = "eg. First Edition" + text = stringResource(Res.string.eg_first_edition) ) }, ) - Text("Source dialect") + Text(stringResource(Res.string.source_dialect)) if (addArtifactUIState.dialects.isEmpty()) { Text( - text = "No dialects have been defined in this group yet. Add one from the group's detail screen first.", + text = stringResource(Res.string.no_dialects_have_been_defined_in_this_group), style = MaterialTheme.typography.bodySmall ) } else { @@ -352,13 +366,13 @@ fun AddArtifactScreen( modifier = Modifier.weight(1f) ) Text( - text = "Direct message detail", + text = stringResource(Res.string.direct_message_detail), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) Text( - text = "Direct message functionality will be here.", + text = stringResource(Res.string.direct_message_functionality_will_be_here), style = MaterialTheme.typography.bodySmall, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddChapterScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddChapterScreen.kt index cf5958a1..71290ac7 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddChapterScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddChapterScreen.kt @@ -54,6 +54,15 @@ import press.mantra.compose.ui.theme.TorchTheme import press.mantra.compose.ui.view.model.AddChapterViewModel import press.mantra.compose.ui.view.state.AddChapterUIState import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.add_chapter +import mantra.composeapp.generated.resources.chapter_name +import mantra.composeapp.generated.resources.eg_chapter_1_the_beginning +import mantra.composeapp.generated.resources.original_text_markdown +import mantra.composeapp.generated.resources.paste_the_chapter_s_markdown_blank_lines +import mantra.composeapp.generated.resources.propose_chapter +import mantra.composeapp.generated.resources.this_artifact_has_no_version_for_a_chapter @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -197,7 +206,7 @@ fun AddChapterScreen( Icons.Default.Add, contentDescription = "Propose chapter" ) - Text("Propose chapter") + Text(stringResource(Res.string.propose_chapter)) } } ) @@ -216,7 +225,7 @@ fun AddChapterScreen( ) } else if (artifactVersion == null) { Text( - text = "This artifact has no version for a chapter to attach to.", + text = stringResource(Res.string.this_artifact_has_no_version_for_a_chapter), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.error ) @@ -239,15 +248,15 @@ fun AddChapterScreen( contentDescription = "Name of the chapter" ) }, - label = { Text("Chapter name") }, - placeholder = { Text("eg. Chapter 1 — The Beginning") }, + label = { Text(stringResource(Res.string.chapter_name)) }, + placeholder = { Text(stringResource(Res.string.eg_chapter_1_the_beginning)) }, ) OutlinedTextField( modifier = Modifier.fillMaxWidth().weight(1f), state = originalTextFieldState, - label = { Text("Original text (markdown)") }, - placeholder = { Text("Paste the chapter's markdown. Blank lines separate paragraphs into chunks.") }, + label = { Text(stringResource(Res.string.original_text_markdown)) }, + placeholder = { Text(stringResource(Res.string.paste_the_chapter_s_markdown_blank_lines)) }, ) Text( @@ -276,7 +285,7 @@ fun AddChapterScreen( ) { Spacer(modifier = Modifier.weight(1f)) Text( - text = "Add chapter", + text = stringResource(Res.string.add_chapter), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddDialectScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddDialectScreen.kt index 7df205dd..64d28e0d 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddDialectScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddDialectScreen.kt @@ -56,6 +56,17 @@ import press.mantra.compose.ui.theme.TorchTheme import press.mantra.compose.ui.view.model.AddDialectViewModel import press.mantra.compose.ui.view.state.AddDialectUIState import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.add_a_dialect_the_group_can_translate_into +import mantra.composeapp.generated.resources.add_dialect +import mantra.composeapp.generated.resources.country +import mantra.composeapp.generated.resources.dialect_name +import mantra.composeapp.generated.resources.eg_lesotho +import mantra.composeapp.generated.resources.eg_sesotho +import mantra.composeapp.generated.resources.eg_st +import mantra.composeapp.generated.resources.language +import mantra.composeapp.generated.resources.propose_dialect @OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class) @Composable @@ -174,7 +185,7 @@ fun AddDialectScreen( Icons.Default.Add, contentDescription = "Propose dialect" ) - Text("Propose dialect") + Text(stringResource(Res.string.propose_dialect)) } } ) @@ -188,7 +199,7 @@ fun AddDialectScreen( verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.space125), horizontalAlignment = Alignment.CenterHorizontally ) { - Text("Add a dialect the group can translate into") + Text(stringResource(Res.string.add_a_dialect_the_group_can_translate_into)) if (!addDialectUIState.canSign) { Text( @@ -216,12 +227,12 @@ fun AddDialectScreen( }, label = { Text( - text = "Dialect name" + text = stringResource(Res.string.dialect_name) ) }, placeholder = { Text( - text = "eg. Sesotho" + text = stringResource(Res.string.eg_sesotho) ) }, ) @@ -243,12 +254,12 @@ fun AddDialectScreen( }, label = { Text( - text = "Country" + text = stringResource(Res.string.country) ) }, placeholder = { Text( - text = "eg. Lesotho" + text = stringResource(Res.string.eg_lesotho) ) }, ) @@ -270,12 +281,12 @@ fun AddDialectScreen( }, label = { Text( - text = "Language" + text = stringResource(Res.string.language) ) }, placeholder = { Text( - text = "eg. st" + text = stringResource(Res.string.eg_st) ) }, ) @@ -296,7 +307,7 @@ fun AddDialectScreen( modifier = Modifier.weight(1f) ) Text( - text = "Add dialect", + text = stringResource(Res.string.add_dialect), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddMemberToChatRoomConfirmationScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddMemberToChatRoomConfirmationScreen.kt index 1670219d..4f90886b 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddMemberToChatRoomConfirmationScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddMemberToChatRoomConfirmationScreen.kt @@ -38,6 +38,11 @@ import press.mantra.compose.ui.view.model.AddMemberToChatRoomConfirmationViewMod import press.mantra.compose.ui.view.state.AddMemberToChatRoomConfirmationUIState import com.vitorpamplona.quartz.nip01Core.core.HexKey import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.direct_message_detail +import mantra.composeapp.generated.resources.direct_message_functionality_will_be_here +import mantra.composeapp.generated.resources.invite @OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class) @Composable @@ -135,7 +140,7 @@ fun AddMemberToChatRoomConfirmationScreen( modifier = Modifier.weight(1f) ) - Text("Invite") + Text(stringResource(Res.string.invite)) Text( text = addMemberToChatRoomConfirmationUIState.profile.humanReadableNameOrPubkey() @@ -170,13 +175,13 @@ fun AddMemberToChatRoomConfirmationScreen( modifier = Modifier.weight(1f) ) Text( - text = "Direct message detail", + text = stringResource(Res.string.direct_message_detail), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) Text( - text = "Direct message functionality will be here.", + text = stringResource(Res.string.direct_message_functionality_will_be_here), style = MaterialTheme.typography.bodySmall, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddTranslationArtifactVersionScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddTranslationArtifactVersionScreen.kt index 03b489f6..c8c35fa3 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddTranslationArtifactVersionScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddTranslationArtifactVersionScreen.kt @@ -58,6 +58,12 @@ import press.mantra.compose.ui.theme.TorchTheme import press.mantra.compose.ui.view.model.AddTranslationArtifactVersionViewModel import press.mantra.compose.ui.view.state.AddTranslationArtifactVersionUIState import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.add_translation +import mantra.composeapp.generated.resources.propose_translation +import mantra.composeapp.generated.resources.this_artifact_has_no_version_for_a +import mantra.composeapp.generated.resources.translate_into_which_dialect @OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class) @Composable @@ -201,7 +207,7 @@ fun AddTranslationArtifactVersionScreen( Icons.Default.Translate, contentDescription = "Propose translation" ) - Text("Propose translation") + Text(stringResource(Res.string.propose_translation)) } } ) @@ -220,13 +226,13 @@ fun AddTranslationArtifactVersionScreen( ) } else if (artifactVersion == null) { Text( - text = "This artifact has no version for a translation to be of.", + text = stringResource(Res.string.this_artifact_has_no_version_for_a), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.error ) } - Text("Translate into which dialect?") + Text(stringResource(Res.string.translate_into_which_dialect)) if (addTranslationUIState.dialects.isEmpty()) { // The only way out of this screen, and it is not on it: @@ -283,7 +289,7 @@ fun AddTranslationArtifactVersionScreen( ) { Spacer(modifier = Modifier.weight(1f)) Text( - text = "Add translation", + text = stringResource(Res.string.add_translation), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ArtifactDetailScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ArtifactDetailScreen.kt index 816f01b5..13eaf2a4 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ArtifactDetailScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ArtifactDetailScreen.kt @@ -49,6 +49,19 @@ import press.mantra.compose.ui.theme.TorchTheme import press.mantra.compose.ui.view.model.ArtifactDetailViewModel import press.mantra.compose.ui.view.state.ArtifactDetailUIState import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.add_chapter +import mantra.composeapp.generated.resources.add_translation +import mantra.composeapp.generated.resources.artifact_detail +import mantra.composeapp.generated.resources.chapters +import mantra.composeapp.generated.resources.details +import mantra.composeapp.generated.resources.no_chapters_yet +import mantra.composeapp.generated.resources.no_translations_yet +import mantra.composeapp.generated.resources.no_versions +import mantra.composeapp.generated.resources.translations +import mantra.composeapp.generated.resources.version +import mantra.composeapp.generated.resources.versions @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -108,12 +121,12 @@ fun ArtifactDetailScreen( // Chapters item { Text( - text = "Chapters", + text = stringResource(Res.string.chapters), style = MaterialTheme.typography.labelMedium ) } if (artifactDetailUIState.chapters.isEmpty()) { - item { Text("No chapters yet.") } + item { Text(stringResource(Res.string.no_chapters_yet)) } } else { items( items = artifactDetailUIState.chapters, @@ -167,7 +180,7 @@ fun ArtifactDetailScreen( contentDescription = "Add chapter" ) Spacer(modifier = Modifier.width(MaterialTheme.spacing.space125)) - Text("Add chapter") + Text(stringResource(Res.string.add_chapter)) } } @@ -176,12 +189,12 @@ fun ArtifactDetailScreen( // Translations item { Text( - text = "Translations", + text = stringResource(Res.string.translations), style = MaterialTheme.typography.labelMedium ) } if (artifactDetailUIState.translations.isEmpty()) { - item { Text("No translations yet.") } + item { Text(stringResource(Res.string.no_translations_yet)) } } else { items( items = artifactDetailUIState.translations, @@ -232,7 +245,7 @@ fun ArtifactDetailScreen( contentDescription = "Add translation" ) Spacer(modifier = Modifier.width(MaterialTheme.spacing.space125)) - Text("Add translation") + Text(stringResource(Res.string.add_translation)) } } @@ -241,7 +254,7 @@ fun ArtifactDetailScreen( // Details item { Text( - text = "Details", + text = stringResource(Res.string.details), style = MaterialTheme.typography.labelMedium ) } @@ -260,12 +273,12 @@ fun ArtifactDetailScreen( // Versions item { Text( - text = "Versions", + text = stringResource(Res.string.versions), style = MaterialTheme.typography.labelMedium ) } if (artifactDetailUIState.versions.isEmpty()) { - item { Text("No versions.") } + item { Text(stringResource(Res.string.no_versions)) } } else { items( items = artifactDetailUIState.versions, @@ -274,7 +287,7 @@ fun ArtifactDetailScreen( Card { ListItem( headlineContent = { Text(version.versionLabel) }, - overlineContent = { Text("Version") } + overlineContent = { Text(stringResource(Res.string.version)) } ) } } @@ -291,7 +304,7 @@ fun ArtifactDetailScreen( ) { Spacer(modifier = Modifier.weight(1f)) Text( - text = "Artifact detail", + text = stringResource(Res.string.artifact_detail), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChapterDetailScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChapterDetailScreen.kt index 7cc799a4..99d5b6fc 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChapterDetailScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChapterDetailScreen.kt @@ -39,6 +39,11 @@ import press.mantra.compose.ui.theme.TorchTheme import press.mantra.compose.ui.view.model.ChapterDetailViewModel import press.mantra.compose.ui.view.state.ChapterDetailUIState import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.chapter_detail +import mantra.composeapp.generated.resources.no_chunks +import mantra.composeapp.generated.resources.original_text @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -104,7 +109,7 @@ fun ChapterDetailScreen( // Original text (markdown, shown as-is). item { Text( - text = "Original text", + text = stringResource(Res.string.original_text), style = MaterialTheme.typography.labelMedium ) } @@ -128,7 +133,7 @@ fun ChapterDetailScreen( ) } if (chapterDetailUIState.chunks.isEmpty()) { - item { Text("No chunks.") } + item { Text(stringResource(Res.string.no_chunks)) } } else { items( items = chapterDetailUIState.chunks, @@ -163,7 +168,7 @@ fun ChapterDetailScreen( ) { Spacer(modifier = Modifier.weight(1f)) Text( - text = "Chapter detail", + text = stringResource(Res.string.chapter_detail), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomCreationScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomCreationScreen.kt index a55ac5fb..9be67274 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomCreationScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomCreationScreen.kt @@ -30,6 +30,15 @@ import press.mantra.compose.ui.composable.navigation.routes.Route import press.mantra.compose.ui.view.model.ChatRoomCreationViewModel import com.vitorpamplona.quartz.nip01Core.core.HexKey import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.choose_who_to_chat_with +import mantra.composeapp.generated.resources.enter_the_name_you_want_to_use_for_your +import mantra.composeapp.generated.resources.name_eg_group_discussions +import mantra.composeapp.generated.resources.this_will_be_shown_when_people_open_the_chat +import mantra.composeapp.generated.resources.this_will_be_the_display_name_for_this_chat +import mantra.composeapp.generated.resources.what_should_people_know_about_you +import mantra.composeapp.generated.resources.what_will_be_discussed_in_this_chat_room @Composable fun ChatRoomCreationScreen( @@ -72,13 +81,13 @@ fun ChatRoomCreationScreen( ), label = { Text( - text = "Name (eg. Group Discussions)", + text = stringResource(Res.string.name_eg_group_discussions), maxLines = 1, ) }, placeholder = { Text( - text = "Enter the name you want to use for your group", + text = stringResource(Res.string.enter_the_name_you_want_to_use_for_your), maxLines = 1, ) }, @@ -91,7 +100,7 @@ fun ChatRoomCreationScreen( ) Text( - text = "This will be the display name for this chat room.", + text = stringResource(Res.string.this_will_be_the_display_name_for_this_chat), style = MaterialTheme.typography.labelMedium, textAlign = TextAlign.Center ) @@ -116,14 +125,14 @@ fun ChatRoomCreationScreen( ), label = { Text( - text = "What will be discussed in this chat room.", + text = stringResource(Res.string.what_will_be_discussed_in_this_chat_room), maxLines = 1, ) }, placeholder = { Text( - text = "What should people know about you?", + text = stringResource(Res.string.what_should_people_know_about_you), maxLines = 1, ) }, @@ -136,7 +145,7 @@ fun ChatRoomCreationScreen( ) Text( - text = "This will be shown when people open the chat for more details.", + text = stringResource(Res.string.this_will_be_shown_when_people_open_the_chat), style = MaterialTheme.typography.labelMedium, textAlign = TextAlign.Center ) @@ -151,7 +160,7 @@ fun ChatRoomCreationScreen( } ) { Text( - "Choose who to chat with" + stringResource(Res.string.choose_who_to_chat_with) ) } } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomDetailScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomDetailScreen.kt index 173705a8..aa4b439b 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomDetailScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomDetailScreen.kt @@ -69,6 +69,26 @@ import press.mantra.compose.ui.composable.navigation.routes.AddArtifactRoute import press.mantra.compose.ui.composable.navigation.routes.AddDialectRoute import press.mantra.compose.ui.composable.navigation.routes.ArtifactDetailRoute import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.add_artifact_to_library +import mantra.composeapp.generated.resources.add_dialect +import mantra.composeapp.generated.resources.create_project +import mantra.composeapp.generated.resources.delete_group +import mantra.composeapp.generated.resources.dialects +import mantra.composeapp.generated.resources.direct_message_detail +import mantra.composeapp.generated.resources.direct_message_functionality_will_be_here +import mantra.composeapp.generated.resources.invite_new_member +import mantra.composeapp.generated.resources.leave_group +import mantra.composeapp.generated.resources.library +import mantra.composeapp.generated.resources.members_2 +import mantra.composeapp.generated.resources.no_artifacts_exists_in_this_groups_library +import mantra.composeapp.generated.resources.no_dialects_have_been_defined_in_this_group_2 +import mantra.composeapp.generated.resources.no_projects_exists_in_this_group +import mantra.composeapp.generated.resources.projects +import mantra.composeapp.generated.resources.proposals +import mantra.composeapp.generated.resources.reindex_events +import mantra.composeapp.generated.resources.shared_key @OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class) @Composable @@ -144,14 +164,14 @@ fun ChatRoomDetailScreen( item { // Artifacts Text( - text = "Library", + text = stringResource(Res.string.library), style = MaterialTheme.typography.labelMedium ) } if (chatRoomDetailUIState.artifacts.isEmpty()) { item { - Text("No artifacts exists in this groups library.") + Text(stringResource(Res.string.no_artifacts_exists_in_this_groups_library)) } } else { items( @@ -217,7 +237,7 @@ fun ChatRoomDetailScreen( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Add artifact to library") + Text(stringResource(Res.string.add_artifact_to_library)) } } @@ -228,14 +248,14 @@ fun ChatRoomDetailScreen( item { // Dialects Text( - text = "Dialects", + text = stringResource(Res.string.dialects), style = MaterialTheme.typography.labelMedium ) } if (chatRoomDetailUIState.dialects.isEmpty()) { item { - Text("No dialects have been defined in this group.") + Text(stringResource(Res.string.no_dialects_have_been_defined_in_this_group_2)) } } else { items( @@ -283,7 +303,7 @@ fun ChatRoomDetailScreen( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Add dialect") + Text(stringResource(Res.string.add_dialect)) } } @@ -296,13 +316,13 @@ fun ChatRoomDetailScreen( item { // Artifacts Text( - text = "Projects", + text = stringResource(Res.string.projects), style = MaterialTheme.typography.labelMedium ) } item { - Text("No projects exists in this group.") + Text(stringResource(Res.string.no_projects_exists_in_this_group)) } item { @@ -326,7 +346,7 @@ fun ChatRoomDetailScreen( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Create project") + Text(stringResource(Res.string.create_project)) } } @@ -336,7 +356,7 @@ fun ChatRoomDetailScreen( item { Text( - text = "members", + text = stringResource(Res.string.members_2), style = MaterialTheme.typography.labelMedium ) } @@ -365,7 +385,7 @@ fun ChatRoomDetailScreen( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Shared key") + Text(stringResource(Res.string.shared_key)) } } } @@ -399,7 +419,7 @@ fun ChatRoomDetailScreen( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Proposals") + Text(stringResource(Res.string.proposals)) } } @@ -426,7 +446,7 @@ fun ChatRoomDetailScreen( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Invite new member") + Text(stringResource(Res.string.invite_new_member)) } } @@ -503,7 +523,7 @@ fun ChatRoomDetailScreen( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Leave group") + Text(stringResource(Res.string.leave_group)) } // What it actually does: sets leftGroupAt and posts a line to @@ -544,7 +564,7 @@ fun ChatRoomDetailScreen( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Delete group") + Text(stringResource(Res.string.delete_group)) } // A soft delete: it sets deletedAt on the local row. Saying @@ -596,13 +616,13 @@ fun ChatRoomDetailScreen( modifier = Modifier.weight(1f) ) Text( - text = "Direct message detail", + text = stringResource(Res.string.direct_message_detail), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) Text( - text = "Direct message functionality will be here.", + text = stringResource(Res.string.direct_message_functionality_will_be_here), style = MaterialTheme.typography.bodySmall, textAlign = TextAlign.Center ) @@ -663,7 +683,7 @@ private fun ReindexMarmotGroupEventsButton( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Reindex events") + Text(stringResource(Res.string.reindex_events)) } when (reindexState) { diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomMessagingScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomMessagingScreen.kt index e33b746f..aa0ed424 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomMessagingScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomMessagingScreen.kt @@ -58,6 +58,12 @@ import press.mantra.compose.ui.view.state.ChatRoomMessagingUIState import com.vitorpamplona.quartz.nip01Core.core.HexKey import press.mantra.compose.ui.theme.spacing import press.mantra.compose.ui.composable.widgets.Decorative +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.creating_new_chat +import mantra.composeapp.generated.resources.direct_message_detail +import mantra.composeapp.generated.resources.direct_message_functionality_will_be_here +import mantra.composeapp.generated.resources.say_what_now @OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class) @Composable @@ -280,7 +286,7 @@ fun ChatRoomMessagingScreen( text = if (directMessageRecipient != null) { "Private message to ${chatMessageListViewModel.nameFor(directMessageRecipient.participantPublicKey)}" } else { - "Say what now?" + stringResource(Res.string.say_what_now) } ) }, @@ -380,13 +386,13 @@ fun ChatRoomMessagingScreen( modifier = Modifier.weight(1f) ) Text( - text = "Direct message detail", + text = stringResource(Res.string.direct_message_detail), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) Text( - text = "Direct message functionality will be here.", + text = stringResource(Res.string.direct_message_functionality_will_be_here), style = MaterialTheme.typography.bodySmall, textAlign = TextAlign.Center ) @@ -413,7 +419,7 @@ fun ChatRoomMessagingScreen( ) Text( - text = "Creating new chat.", + text = stringResource(Res.string.creating_new_chat), style = MaterialTheme.typography.bodySmall, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/CreateProfileScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/CreateProfileScreen.kt index 4f2102e3..035310fa 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/CreateProfileScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/CreateProfileScreen.kt @@ -37,6 +37,28 @@ import press.mantra.compose.ui.theme.LocalExtendedColors import press.mantra.compose.ui.view.model.CreateProfileViewModel import press.mantra.compose.ui.view.state.CreateProfileUIState import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.after_this_there_is_no_turning_back +import mantra.composeapp.generated.resources.bio +import mantra.composeapp.generated.resources.create_profile +import mantra.composeapp.generated.resources.end_this +import mantra.composeapp.generated.resources.enter_the_name_you_want_to_use_for_your_2 +import mantra.composeapp.generated.resources.introduce_yourself +import mantra.composeapp.generated.resources.it_is_cryptographical_secure_and +import mantra.composeapp.generated.resources.name +import mantra.composeapp.generated.resources.name_eg_alan_turing +import mantra.composeapp.generated.resources.next +import mantra.composeapp.generated.resources.profile_is_ready +import mantra.composeapp.generated.resources.see_how_deep_the_rabbit_hole_goes +import mantra.composeapp.generated.resources.something_went_wrong_and_we_were_unable_to_2 +import mantra.composeapp.generated.resources.start +import mantra.composeapp.generated.resources.the_above_will_be_your_profile +import mantra.composeapp.generated.resources.this_will_be_shown_when_people_open_your +import mantra.composeapp.generated.resources.this_will_be_the_display_name_for_your +import mantra.composeapp.generated.resources.what_should_people_know_about_you +import mantra.composeapp.generated.resources.you_are_about_to_create_a_nostr_profile +import mantra.composeapp.generated.resources.you_will_be_in_full_control_of_this_profile @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -73,18 +95,18 @@ fun CreateProfileScreen( is CreateProfileUIState.Declaration -> { Text( - "Create profile", + stringResource(Res.string.create_profile), style = MaterialTheme.typography.headlineSmall ) Text( - "You are about to create a NOSTR profile.", + stringResource(Res.string.you_are_about_to_create_a_nostr_profile), style = MaterialTheme.typography.bodyMedium, textAlign = TextAlign.Center ) Text( - "It is cryptographical secure, and decentralized, putting you in total control of your digital profile", + stringResource(Res.string.it_is_cryptographical_secure_and), style = MaterialTheme.typography.bodyMedium, textAlign = TextAlign.Center ) @@ -100,13 +122,13 @@ fun CreateProfileScreen( } ) { Text( - text = "Start" + text = stringResource(Res.string.start) ) } } is CreateProfileUIState.InputPrompt -> { Text( - "Create profile", + stringResource(Res.string.create_profile), style = MaterialTheme.typography.headlineSmall ) @@ -134,13 +156,13 @@ fun CreateProfileScreen( ), label = { Text( - text = "Name (eg. Alan Turing)", + text = stringResource(Res.string.name_eg_alan_turing), maxLines = 1, ) }, placeholder = { Text( - text = "Enter the name you want to use for your profile", + text = stringResource(Res.string.enter_the_name_you_want_to_use_for_your_2), maxLines = 1, ) }, @@ -153,7 +175,7 @@ fun CreateProfileScreen( ) Text( - text = "This will be the display name for your profile and also important for search.", + text = stringResource(Res.string.this_will_be_the_display_name_for_your), style = MaterialTheme.typography.labelMedium, textAlign = TextAlign.Center ) @@ -178,14 +200,14 @@ fun CreateProfileScreen( ), label = { Text( - text = "Introduce yourself", + text = stringResource(Res.string.introduce_yourself), maxLines = 1, ) }, placeholder = { Text( - text = "What should people know about you?", + text = stringResource(Res.string.what_should_people_know_about_you), maxLines = 1, ) }, @@ -198,7 +220,7 @@ fun CreateProfileScreen( ) Text( - text = "This will be shown when people open your profile.", + text = stringResource(Res.string.this_will_be_shown_when_people_open_your), style = MaterialTheme.typography.labelMedium, textAlign = TextAlign.Center ) @@ -220,7 +242,7 @@ fun CreateProfileScreen( } ) { Text( - "Next" + stringResource(Res.string.next) ) } @@ -228,7 +250,7 @@ fun CreateProfileScreen( is CreateProfileUIState.ConfirmInput -> { Text( - text = "Name", + text = stringResource(Res.string.name), style = MaterialTheme.typography.labelLarge ) @@ -239,7 +261,7 @@ fun CreateProfileScreen( ) Text( - text = "Bio", + text = stringResource(Res.string.bio), style = MaterialTheme.typography.labelLarge ) @@ -252,7 +274,7 @@ fun CreateProfileScreen( Text( - text = "The above will be your profile.", + text = stringResource(Res.string.the_above_will_be_your_profile), style = MaterialTheme.typography.bodySmall ) @@ -261,7 +283,7 @@ fun CreateProfileScreen( ) Text( - text = "You will be in full control of this profile. If you would like to use it for the long term please remember to backup the profile/keys.", + text = stringResource(Res.string.you_will_be_in_full_control_of_this_profile), style = MaterialTheme.typography.labelSmall, textAlign = TextAlign.Center ) @@ -277,7 +299,7 @@ fun CreateProfileScreen( } ) { Text( - text = "Create profile" + text = stringResource(Res.string.create_profile) ) } } @@ -288,7 +310,7 @@ fun CreateProfileScreen( modifier = Modifier.weight(1f) ) Text( - text = "Something went wrong and we were unable to sign you up. Please try again later.", + text = stringResource(Res.string.something_went_wrong_and_we_were_unable_to_2), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) @@ -308,13 +330,13 @@ fun CreateProfileScreen( modifier = Modifier.weight(1f) ) Text( - text = "Profile is ready", + text = stringResource(Res.string.profile_is_ready), style = MaterialTheme.typography.headlineLarge, textAlign = TextAlign.Center ) Text( - text = "After this there is no turning back." + text = stringResource(Res.string.after_this_there_is_no_turning_back) ) Button( @@ -327,7 +349,7 @@ fun CreateProfileScreen( } ) { Text( - text = "See how deep the rabbit hole goes" + text = stringResource(Res.string.see_how_deep_the_rabbit_hole_goes) ) } @@ -348,7 +370,7 @@ fun CreateProfileScreen( } ) { Text( - text = "end this" + text = stringResource(Res.string.end_this) ) } Spacer( diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgApprovalScaffold.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgApprovalScaffold.kt index 30352f13..96ea36e4 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgApprovalScaffold.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgApprovalScaffold.kt @@ -39,6 +39,10 @@ import fr.acinq.phoenix.data.ActiveWallet import kotlinx.coroutines.flow.StateFlow import press.mantra.compose.ui.theme.spacing import press.mantra.compose.ui.composable.widgets.Decorative +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.back +import mantra.composeapp.generated.resources.not_now /** * The frame every ChillDKG approval screen sits in: the view model, the states @@ -149,7 +153,7 @@ internal fun DkgApprovalScaffold( color = MaterialTheme.colorScheme.onSurfaceVariant, textAlign = TextAlign.Center ) - TextButton(onClick = onDone) { Text(text = "Back") } + TextButton(onClick = onDone) { Text(text = stringResource(Res.string.back)) } } return@Scaffold @@ -181,7 +185,7 @@ internal fun DkgApprovalScaffold( onClick = onDone, enabled = !isActionPending ) { - Text(text = "Not now") + Text(text = stringResource(Res.string.not_now)) } Button( diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgRitualScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgRitualScreen.kt index 9066e5f2..56d52939 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgRitualScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgRitualScreen.kt @@ -77,6 +77,24 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import press.mantra.compose.ui.theme.spacing import press.mantra.compose.ui.composable.widgets.Decorative +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.create_the_admins_group +import mantra.composeapp.generated.resources.how_many_members_will_it_take_to_sign +import mantra.composeapp.generated.resources.key +import mantra.composeapp.generated.resources.members +import mantra.composeapp.generated.resources.nothing_was_created_and_no_key_exists_it_is +import mantra.composeapp.generated.resources.review_and_confirm +import mantra.composeapp.generated.resources.review_and_contribute +import mantra.composeapp.generated.resources.review_and_join +import mantra.composeapp.generated.resources.shared_key +import mantra.composeapp.generated.resources.start_key_ceremony +import mantra.composeapp.generated.resources.the_ceremony_was_abandoned +import mantra.composeapp.generated.resources.the_group_can_hold_one_key_together_split_so +import mantra.composeapp.generated.resources.the_group_has_a_shared_key +import mantra.composeapp.generated.resources.this_is_fixed_once_the_ceremony_runs +import mantra.composeapp.generated.resources.try_again +import mantra.composeapp.generated.resources.your_share_of_it_is_on_this_device_only_your /** * The shared-key ceremony: a ChillDKG ritual run across the group's NIP-17 @@ -169,9 +187,9 @@ fun DkgRitualScreen( Icon(Icons.Default.Key, contentDescription = Decorative) Text( text = when (pending) { - DkgApprovalStep.HOST_KEY -> "Review and join" - DkgApprovalStep.ROUND_1 -> "Review and contribute" - DkgApprovalStep.ROUND_2 -> "Review and confirm" + DkgApprovalStep.HOST_KEY -> stringResource(Res.string.review_and_join) + DkgApprovalStep.ROUND_1 -> stringResource(Res.string.review_and_contribute) + DkgApprovalStep.ROUND_2 -> stringResource(Res.string.review_and_confirm) } ) } @@ -197,7 +215,7 @@ fun DkgRitualScreen( } Text( - text = if (session == null) "Start key ceremony" else "Try again" + text = if (session == null) stringResource(Res.string.start_key_ceremony) else stringResource(Res.string.try_again) ) } }, @@ -222,7 +240,7 @@ fun DkgRitualScreen( ) { if (session == null) { Text( - text = "The group can hold one key together, split so that no single member holds it. Signing with it takes a quorum.", + text = stringResource(Res.string.the_group_can_hold_one_key_together_split_so), style = MaterialTheme.typography.bodyMedium ) @@ -272,7 +290,7 @@ fun DkgRitualScreen( ) { Spacer(modifier = Modifier.weight(1f)) Text( - text = "Shared key", + text = stringResource(Res.string.shared_key), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) @@ -336,12 +354,12 @@ private fun RitualProgress( ) { Icon(Icons.Default.ErrorOutline, contentDescription = Decorative) Column(verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.relatedGap)) { - Text("The ceremony was abandoned.", style = MaterialTheme.typography.titleSmall) + Text(stringResource(Res.string.the_ceremony_was_abandoned), style = MaterialTheme.typography.titleSmall) session.failureReason?.let { Text(it, style = MaterialTheme.typography.bodyMedium) } Text( - "Nothing was created and no key exists. It is safe to run it again.", + stringResource(Res.string.nothing_was_created_and_no_key_exists_it_is), style = MaterialTheme.typography.labelMedium ) } @@ -406,13 +424,13 @@ private fun RitualProgress( verticalAlignment = Alignment.CenterVertically ) { Icon(Icons.Default.CheckCircle, contentDescription = Decorative) - Text("The group has a shared key.", style = MaterialTheme.typography.titleSmall) + Text(stringResource(Res.string.the_group_has_a_shared_key), style = MaterialTheme.typography.titleSmall) } session.thresholdPublicKey?.let { thresholdPublicKey -> val clipboardManager = LocalClipboardManager.current - Text(text = "Key", style = MaterialTheme.typography.labelMedium) + Text(text = stringResource(Res.string.key), style = MaterialTheme.typography.labelMedium) Row( modifier = Modifier.fillMaxWidth(), @@ -445,7 +463,7 @@ private fun RitualProgress( } Text( - text = "Your share of it is on this device only. Your wallet backup restores it — nobody else's share can.", + text = stringResource(Res.string.your_share_of_it_is_on_this_device_only_your), style = MaterialTheme.typography.labelMedium ) @@ -476,7 +494,7 @@ private fun RitualProgress( } else { Icon(Icons.Default.Groups, contentDescription = Decorative) Spacer(modifier = Modifier.width(MaterialTheme.spacing.space100)) - Text(text = "Create the #admins group") + Text(text = stringResource(Res.string.create_the_admins_group)) } } } @@ -506,7 +524,7 @@ private fun RitualRoster( modifier = Modifier.fillMaxWidth().padding(MaterialTheme.spacing.space200), verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.space125) ) { - Text(text = "Members", style = MaterialTheme.typography.titleSmall) + Text(text = stringResource(Res.string.members), style = MaterialTheme.typography.titleSmall) members .sortedBy { it.participant.participantPublicKey } @@ -616,7 +634,7 @@ private fun QuorumStepper( verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.space50) ) { Text( - text = "How many members will it take to sign?", + text = stringResource(Res.string.how_many_members_will_it_take_to_sign), style = MaterialTheme.typography.titleSmall ) @@ -646,7 +664,7 @@ private fun QuorumStepper( } Text( - text = "This is fixed once the ceremony runs. Changing it later means generating a new key.", + text = stringResource(Res.string.this_is_fixed_once_the_ceremony_runs), style = MaterialTheme.typography.labelMedium ) } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgRound1ApprovalScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgRound1ApprovalScreen.kt index 18d22550..f8b3babe 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgRound1ApprovalScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgRound1ApprovalScreen.kt @@ -15,6 +15,10 @@ import com.vitorpamplona.quartz.nip01Core.core.HexKey import fr.acinq.phoenix.data.ActiveWallet import kotlinx.coroutines.flow.StateFlow import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.taking_part_with_these_members +import mantra.composeapp.generated.resources.you /** * Asks whether to contribute to the key itself. @@ -69,7 +73,7 @@ fun DkgRound1ApprovalScreen( } Text( - text = "Taking part with these members", + text = stringResource(Res.string.taking_part_with_these_members), style = MaterialTheme.typography.titleSmall ) @@ -82,7 +86,7 @@ fun DkgRound1ApprovalScreen( Text( text = if (key == activeUserPublicKey) { - "You" + stringResource(Res.string.you) } else { member.profile?.humanReadableNameOrPubkey() ?: key.take(12) }, diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgRound2ApprovalScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgRound2ApprovalScreen.kt index 088cea3c..035c4039 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgRound2ApprovalScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgRound2ApprovalScreen.kt @@ -15,6 +15,9 @@ import com.vitorpamplona.quartz.nip01Core.core.HexKey import fr.acinq.phoenix.data.ActiveWallet import kotlinx.coroutines.flow.StateFlow import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.this_is_the_last_thing_the_ceremony_needs /** * Asks whether to confirm the combined result. @@ -74,7 +77,7 @@ fun DkgRound2ApprovalScreen( } Text( - text = "This is the last thing the ceremony needs from you.", + text = stringResource(Res.string.this_is_the_last_thing_the_ceremony_needs), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/FrostSigningScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/FrostSigningScreen.kt index 1e7e9da2..08d39f6f 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/FrostSigningScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/FrostSigningScreen.kt @@ -58,6 +58,16 @@ import press.mantra.compose.ui.view.model.FrostSigningViewModel import press.mantra.compose.ui.view.state.FrostSigningUIState import press.mantra.compose.ui.theme.spacing import press.mantra.compose.ui.composable.widgets.Decorative +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.don_t_sign +import mantra.composeapp.generated.resources.has_not_taken_part_yet +import mantra.composeapp.generated.resources.members +import mantra.composeapp.generated.resources.read_to_the_end_of_the_list_to_sign +import mantra.composeapp.generated.resources.ready_to_sign +import mantra.composeapp.generated.resources.sign +import mantra.composeapp.generated.resources.sign_with_the_group_s_key +import mantra.composeapp.generated.resources.signed_their_part /** * One signing session, and the member's decision about it. @@ -105,7 +115,7 @@ fun FrostSigningScreen( TopAppBar( title = { Text( - text = "Sign with the group's key", + text = stringResource(Res.string.sign_with_the_group_s_key), maxLines = 1, overflow = TextOverflow.Ellipsis ) @@ -174,7 +184,7 @@ fun FrostSigningScreen( HorizontalDivider() Text( - text = "Members", + text = stringResource(Res.string.members), style = MaterialTheme.typography.labelMedium ) @@ -224,9 +234,9 @@ fun FrostSigningScreen( supportingContent = { Text( text = when { - member in state.signed -> "Signed their part" - member in state.offeredNonce -> "Ready to sign" - else -> "Has not taken part yet" + member in state.signed -> stringResource(Res.string.signed_their_part) + member in state.offeredNonce -> stringResource(Res.string.ready_to_sign) + else -> stringResource(Res.string.has_not_taken_part_yet) } ) } @@ -260,7 +270,7 @@ fun FrostSigningScreen( if (readable && !seenEverything) { Text( - text = "Read to the end of the list to sign.", + text = stringResource(Res.string.read_to_the_end_of_the_list_to_sign), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant ) @@ -278,7 +288,7 @@ fun FrostSigningScreen( ) { Icon(Icons.Default.Draw, contentDescription = Decorative) Spacer(modifier = Modifier.width(MaterialTheme.spacing.space125)) - Text("Sign") + Text(stringResource(Res.string.sign)) } // Declining stays available whatever the screen could @@ -293,7 +303,7 @@ fun FrostSigningScreen( enabled = !frostSigningViewModel.isActionPending.value, onClick = { frostSigningViewModel.decline(onNavigateBack) } ) { - Text("Don't sign") + Text(stringResource(Res.string.don_t_sign)) } } } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/HomeScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/HomeScreen.kt index 2e892a44..e1c08bd1 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/HomeScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/HomeScreen.kt @@ -57,6 +57,11 @@ import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent import kotlinx.coroutines.launch import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.mantra +import mantra.composeapp.generated.resources.new_chat +import mantra.composeapp.generated.resources.something_went_wrong @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -96,7 +101,7 @@ fun HomeScreen( modifier = Modifier.weight(1f) ) Text( - text = "Something went wrong" + text = stringResource(Res.string.something_went_wrong) ) Spacer( @@ -122,7 +127,7 @@ fun HomeScreen( // the other, and is left alone -- it goes on the wire to relay // operators, so it is a network identity question rather than // a content one. - Text("Mantra") + Text(stringResource(Res.string.mantra)) }, navigationIcon = { IconButton( @@ -168,7 +173,7 @@ fun HomeScreen( ) }, text = { - Text("New chat") + Text(stringResource(Res.string.new_chat)) } ) } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/KeyPackageManagementScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/KeyPackageManagementScreen.kt index 17a0d80a..b3e3f4cd 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/KeyPackageManagementScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/KeyPackageManagementScreen.kt @@ -44,6 +44,12 @@ import press.mantra.compose.ui.view.model.KeyPackageManagementViewModel import press.mantra.compose.ui.view.state.KeyPackageManagementUIState import com.vitorpamplona.quartz.nip01Core.core.HexKey import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.key_package_management +import mantra.composeapp.generated.resources.publish_new_key_package +import mantra.composeapp.generated.resources.something_went_wrong +import mantra.composeapp.generated.resources.we_couldn_t_find_the_local_profile_please @OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class) @Composable @@ -72,7 +78,7 @@ fun KeyPackageManagementScreen( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { - Text("Something went wrong") + Text(stringResource(Res.string.something_went_wrong)) } } is KeyPackageManagementUIState.Loaded -> { @@ -81,7 +87,7 @@ fun KeyPackageManagementScreen( TopAppBar( title = { Text( - text = "Key package management" + text = stringResource(Res.string.key_package_management) ) }, navigationIcon = { @@ -123,7 +129,7 @@ fun KeyPackageManagementScreen( ) Text( - text = "Publish new key package" + text = stringResource(Res.string.publish_new_key_package) ) } } @@ -213,7 +219,7 @@ fun KeyPackageManagementScreen( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { - Text("We couldn't find the local profile. Please try again later.") + Text(stringResource(Res.string.we_couldn_t_find_the_local_profile_please)) } } } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/LandingScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/LandingScreen.kt index 40b1af2a..7aecc3fa 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/LandingScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/LandingScreen.kt @@ -20,6 +20,15 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.create_profile +import mantra.composeapp.generated.resources.if_you_are_new_to_torch_or_just_want_to +import mantra.composeapp.generated.resources.keep_the_feed_alive +import mantra.composeapp.generated.resources.learn_more +import mantra.composeapp.generated.resources.mantra +import mantra.composeapp.generated.resources.sign_in +import mantra.composeapp.generated.resources.sign_in_to_torch_via_nsec_or_remote_signer @Composable fun LandingScreen( @@ -37,19 +46,19 @@ fun LandingScreen( horizontalAlignment = Alignment.CenterHorizontally ) { Text( - text = "Mantra", + text = stringResource(Res.string.mantra), style = MaterialTheme.typography.headlineLarge ) Text( - text = "Keep the feed alive." + text = stringResource(Res.string.keep_the_feed_alive) ) TextButton( onClick = onNavigateToLearnMore ) { Text( - text = "Learn more", + text = stringResource(Res.string.learn_more), style = MaterialTheme.typography.labelLarge, ) } @@ -63,13 +72,13 @@ fun LandingScreen( ) { Text( - "Sign in", + stringResource(Res.string.sign_in), style = MaterialTheme.typography.bodyLarge ) } Text( - text = "Sign in to Torch via nsec, or remote signer", + text = stringResource(Res.string.sign_in_to_torch_via_nsec_or_remote_signer), modifier = Modifier.padding(MaterialTheme.spacing.space125), style = MaterialTheme.typography.labelSmall, textAlign = TextAlign.Center @@ -83,13 +92,13 @@ fun LandingScreen( onClick = onNavigateToCreateProfile ) { Text( - "Create profile", + stringResource(Res.string.create_profile), style = MaterialTheme.typography.bodyLarge ) } Text( - text = "If you are new to Torch or just want to create a fresh profile", + text = stringResource(Res.string.if_you_are_new_to_torch_or_just_want_to), modifier = Modifier.padding(MaterialTheme.spacing.space125), style = MaterialTheme.typography.labelSmall, textAlign = TextAlign.Center diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/NostrEventDetailScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/NostrEventDetailScreen.kt index 878fe401..269968af 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/NostrEventDetailScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/NostrEventDetailScreen.kt @@ -32,6 +32,12 @@ import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent import com.vitorpamplona.quartz.nip18Reposts.RepostEvent import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.functionality_coming_soon +import mantra.composeapp.generated.resources.post_functionality_coming_soon +import mantra.composeapp.generated.resources.something_went_wrong +import mantra.composeapp.generated.resources.we_couldn_t_find_your_nostr_event_please_try @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -63,7 +69,7 @@ fun NostrEventDetailScreen( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { - Text("Something went wrong") + Text(stringResource(Res.string.something_went_wrong)) } } is NostrEventDetailUIState.Loaded -> { @@ -98,7 +104,7 @@ fun NostrEventDetailScreen( ) { Text(feedListUIState.localNostrEvent.nostrEvent.content) - Text("post functionality coming soon.") + Text(stringResource(Res.string.post_functionality_coming_soon)) } } else -> { @@ -113,7 +119,7 @@ fun NostrEventDetailScreen( ) { Text(feedListUIState.localNostrEvent.nostrEvent.content) - Text("functionality coming soon.") + Text(stringResource(Res.string.functionality_coming_soon)) } } } @@ -133,7 +139,7 @@ fun NostrEventDetailScreen( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { - Text("We couldn't find your nostr event. Please try again later.") + Text(stringResource(Res.string.we_couldn_t_find_your_nostr_event_please_try)) } } } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ProposalListScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ProposalListScreen.kt index 32d966f4..aab513c5 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ProposalListScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ProposalListScreen.kt @@ -55,6 +55,13 @@ import press.mantra.compose.ui.theme.TorchTheme import press.mantra.compose.ui.view.model.ProposalListViewModel import press.mantra.compose.ui.view.state.ProposalListUIState import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.everything_else +import mantra.composeapp.generated.resources.proposals +import mantra.composeapp.generated.resources.review +import mantra.composeapp.generated.resources.this_group_has_not_been_asked_to_sign +import mantra.composeapp.generated.resources.waiting_for_you /** * Everything the group has asked its shared key to sign. @@ -102,7 +109,7 @@ fun ProposalListScreen( TopAppBar( title = { Text( - text = "Proposals", + text = stringResource(Res.string.proposals), maxLines = 1, overflow = TextOverflow.Ellipsis ) @@ -151,7 +158,7 @@ fun ProposalListScreen( item { Text( modifier = Modifier.fillMaxWidth().padding(top = MaterialTheme.spacing.space600), - text = "This group has not been asked to sign anything yet.", + text = stringResource(Res.string.this_group_has_not_been_asked_to_sign), textAlign = TextAlign.Center ) } @@ -160,7 +167,7 @@ fun ProposalListScreen( if (state.waitingForYou.isNotEmpty()) { item { Text( - text = "Waiting for you", + text = stringResource(Res.string.waiting_for_you), style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.primary ) @@ -181,7 +188,7 @@ fun ProposalListScreen( if (state.waitingForYou.isNotEmpty()) { item { Text( - text = "Everything else", + text = stringResource(Res.string.everything_else), style = MaterialTheme.typography.labelMedium ) } @@ -296,7 +303,7 @@ private fun ProposalCard( // it saying what it said there. if (proposal.awaitsYou) { Text( - text = "Review", + text = stringResource(Res.string.review), style = MaterialTheme.typography.labelLarge, color = cardContentColor ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SearchMemberToAddToChatRoomScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SearchMemberToAddToChatRoomScreen.kt index 668879fc..1fbcfcbd 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SearchMemberToAddToChatRoomScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SearchMemberToAddToChatRoomScreen.kt @@ -41,6 +41,11 @@ import press.mantra.compose.ui.view.model.SearchMemberToAddToChatRoomViewModel import press.mantra.compose.ui.view.state.SearchMemberToAddToChatRoomUIState import com.vitorpamplona.quartz.nip01Core.core.HexKey import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.currently_no_contacts_please_search_and_chat +import mantra.composeapp.generated.resources.search_member_functionality +import mantra.composeapp.generated.resources.search_message_functionality_will_be_here @OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class) @Composable @@ -110,7 +115,7 @@ fun SearchMemberToAddToChatRoomScreen( ) Text( modifier = Modifier.padding(MaterialTheme.spacing.space250), - text = "Currently no contacts. Please search and chat with a few people.", + text = stringResource(Res.string.currently_no_contacts_please_search_and_chat), textAlign = TextAlign.Center ) @@ -182,13 +187,13 @@ fun SearchMemberToAddToChatRoomScreen( modifier = Modifier.weight(1f) ) Text( - text = "Search member functionality", + text = stringResource(Res.string.search_member_functionality), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) Text( - text = "Search message functionality will be here.", + text = stringResource(Res.string.search_message_functionality_will_be_here), style = MaterialTheme.typography.bodySmall, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SearchResultScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SearchResultScreen.kt index ca4ca0f6..7a096b57 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SearchResultScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SearchResultScreen.kt @@ -55,6 +55,12 @@ import press.mantra.compose.ui.view.model.SearchResultViewModel import press.mantra.compose.ui.view.state.SearchResultListUIState import kotlinx.coroutines.launch import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.no_events_were_found +import mantra.composeapp.generated.resources.profiles +import mantra.composeapp.generated.resources.search +import mantra.composeapp.generated.resources.something_went_wrong @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -109,7 +115,7 @@ fun SearchResultScreen( enabled = false, expanded = expanded, onExpandedChange = { expanded = it }, - placeholder = { Text("Search") }, + placeholder = { Text(stringResource(Res.string.search)) }, leadingIcon = { if (expanded) { IconButton( @@ -200,7 +206,7 @@ fun SearchResultScreen( ) { when(SearchResultType.entries[pageIndex]) { SearchResultType.Profiles -> { - Text("Profiles") + Text(stringResource(Res.string.profiles)) } } @@ -214,7 +220,7 @@ fun SearchResultScreen( modifier = Modifier.height(MaterialTheme.spacing.space600) ) Text( - text = "Something went wrong", + text = stringResource(Res.string.something_went_wrong), ) } } @@ -229,7 +235,7 @@ fun SearchResultScreen( modifier = Modifier.height(MaterialTheme.spacing.space600) ) Text( - text = "No events were found", + text = stringResource(Res.string.no_events_were_found), ) } } else { diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SearchScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SearchScreen.kt index 08ca2a73..93afe8c1 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SearchScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SearchScreen.kt @@ -63,6 +63,13 @@ import press.mantra.compose.ui.theme.TorchTheme import press.mantra.compose.ui.view.model.SearchViewModel import press.mantra.compose.ui.view.state.SearchUIState import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.profiles +import mantra.composeapp.generated.resources.recents +import mantra.composeapp.generated.resources.search +import mantra.composeapp.generated.resources.search_hashtags +import mantra.composeapp.generated.resources.trending_notes_functionality_coming_soon_in @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -117,7 +124,7 @@ fun SearchScreen( }, expanded = expanded, onExpandedChange = { expanded = it }, - placeholder = { Text("Search") }, + placeholder = { Text(stringResource(Res.string.search)) }, leadingIcon = { if (expanded) { IconButton( @@ -156,7 +163,7 @@ fun SearchScreen( }, supportingContent = { Text( - text = "Search" + text = stringResource(Res.string.search) ) }, leadingContent = { @@ -196,7 +203,7 @@ fun SearchScreen( headlineContent = { Text(textFieldState.text.toString()) }, supportingContent = { Text( - text = "Search hashtags" + text = stringResource(Res.string.search_hashtags) ) }, leadingContent = { @@ -289,7 +296,7 @@ fun SearchScreen( modifier = Modifier.padding(MaterialTheme.spacing.space125), ) { Text( - text = "Profiles", + text = stringResource(Res.string.profiles), style = MaterialTheme.typography.titleMedium ) } @@ -344,7 +351,7 @@ fun SearchScreen( modifier = Modifier.padding(MaterialTheme.spacing.space125), ) { Text( - text = "Recents", + text = stringResource(Res.string.recents), style = MaterialTheme.typography.titleMedium ) } @@ -404,7 +411,7 @@ fun SearchScreen( title = {} ) Text( - text = "Trending notes functionality coming soon. In the meantime search for what you are looking for.", + text = stringResource(Res.string.trending_notes_functionality_coming_soon_in), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SelectChatRoomMembersScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SelectChatRoomMembersScreen.kt index f4468b9c..e115d788 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SelectChatRoomMembersScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SelectChatRoomMembersScreen.kt @@ -43,6 +43,13 @@ import press.mantra.compose.ui.view.model.SelectChatRoomMembersViewModel import press.mantra.compose.ui.view.state.SelectChatRoomMembersUIState import com.vitorpamplona.quartz.nip01Core.core.HexKey import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.next +import mantra.composeapp.generated.resources.no_one_selected_yet +import mantra.composeapp.generated.resources.no_one_to_add_yet +import mantra.composeapp.generated.resources.search_for_people_and_chat_with_them_first +import mantra.composeapp.generated.resources.you_can_still_carry_on_and_invite_people /** * Second step of group creation: pick who is in the group. @@ -120,7 +127,7 @@ fun SelectChatRoomMembersScreen( text = if (selectedCount > 0) { "Next with $selectedCount" } else { - "Next" + stringResource(Res.string.next) } ) } @@ -131,7 +138,7 @@ fun SelectChatRoomMembersScreen( text = if (selectedCount > 0) { "$selectedCount selected" } else { - "No one selected yet" + stringResource(Res.string.no_one_selected_yet) }, style = MaterialTheme.typography.labelLarge ) @@ -153,19 +160,19 @@ fun SelectChatRoomMembersScreen( ) Text( - text = "No one to add yet.", + text = stringResource(Res.string.no_one_to_add_yet), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) Text( - text = "Search for people and chat with them first — everyone you know locally shows up here.", + text = stringResource(Res.string.search_for_people_and_chat_with_them_first), style = MaterialTheme.typography.bodySmall, textAlign = TextAlign.Center ) Text( - text = "You can still carry on and invite people later.", + text = stringResource(Res.string.you_can_still_carry_on_and_invite_people), style = MaterialTheme.typography.bodySmall, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SelectChatRoomTypeScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SelectChatRoomTypeScreen.kt index 9a03ffae..3831e0c8 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SelectChatRoomTypeScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SelectChatRoomTypeScreen.kt @@ -57,6 +57,14 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import press.mantra.compose.ui.theme.spacing import press.mantra.compose.ui.composable.widgets.Decorative +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.create_chat +import mantra.composeapp.generated.resources.how_many_admins_have_to_approve_a_change +import mantra.composeapp.generated.resources.just_you_for_now +import mantra.composeapp.generated.resources.open_chat +import mantra.composeapp.generated.resources.this_decides_who_can_change_the_group_later +import mantra.composeapp.generated.resources.you_and_1_other /** * Last step of group creation: convenient (one admin) or robust (everyone @@ -149,9 +157,9 @@ fun SelectChatRoomTypeScreen( Text( text = if (selectChatRoomTypeViewModel.createdChatRoomId.value != null) { - "Open chat" + stringResource(Res.string.open_chat) } else { - "Create chat" + stringResource(Res.string.create_chat) } ) } @@ -160,8 +168,8 @@ fun SelectChatRoomTypeScreen( Text( modifier = Modifier.padding(start = MaterialTheme.spacing.space200), text = when (selectChatRoomTypeUIState.members.size) { - 0 -> "Just you for now" - 1 -> "You and 1 other" + 0 -> stringResource(Res.string.just_you_for_now) + 1 -> stringResource(Res.string.you_and_1_other) else -> "You and ${selectChatRoomTypeUIState.members.size} others" }, style = MaterialTheme.typography.labelLarge @@ -211,7 +219,7 @@ fun SelectChatRoomTypeScreen( } Text( - text = "This decides who can change the group later. You can't switch afterwards.", + text = stringResource(Res.string.this_decides_who_can_change_the_group_later), style = MaterialTheme.typography.labelMedium, textAlign = TextAlign.Center, modifier = Modifier.fillMaxWidth().padding(horizontal = MaterialTheme.spacing.space125) @@ -400,7 +408,7 @@ private fun QuorumPicker( verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.space50) ) { Text( - text = "How many admins have to approve a change?", + text = stringResource(Res.string.how_many_admins_have_to_approve_a_change), style = MaterialTheme.typography.titleSmall ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ShareProfileScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ShareProfileScreen.kt index 012eeb7d..b596258a 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ShareProfileScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ShareProfileScreen.kt @@ -45,6 +45,12 @@ import press.mantra.compose.ui.view.state.ShareProfileUIState import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.profile +import mantra.composeapp.generated.resources.re_broadcast +import mantra.composeapp.generated.resources.something_went_wrong +import mantra.composeapp.generated.resources.we_couldn_t_find_the_local_profile_please @OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class) @Composable @@ -73,7 +79,7 @@ fun ShareProfileScreen( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { - Text("Something went wrong") + Text(stringResource(Res.string.something_went_wrong)) } } is ShareProfileUIState.Loaded -> { @@ -82,7 +88,7 @@ fun ShareProfileScreen( TopAppBar( title = { Text( - text = "Profile" + text = stringResource(Res.string.profile) ) }, navigationIcon = { @@ -192,7 +198,7 @@ fun ShareProfileScreen( } ) { Text( - "Re-broadcast" + stringResource(Res.string.re_broadcast) ) } } @@ -212,7 +218,7 @@ fun ShareProfileScreen( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { - Text("We couldn't find the local profile. Please try again later.") + Text(stringResource(Res.string.we_couldn_t_find_the_local_profile_please)) } } } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SignInScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SignInScreen.kt index 1cbeda64..534e803c 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SignInScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SignInScreen.kt @@ -32,6 +32,18 @@ import androidx.lifecycle.viewmodel.compose.viewModel import com.vitorpamplona.quartz.nip19Bech32.entities.NPub import com.vitorpamplona.quartz.nip19Bech32.entities.NSec import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.be_sure_to_keep_this_nsec_safe +import mantra.composeapp.generated.resources.enter_the_nsec_or_npub_read_only_that_you +import mantra.composeapp.generated.resources.next +import mantra.composeapp.generated.resources.nsec_npub_nip_05_static_address +import mantra.composeapp.generated.resources.sign_in +import mantra.composeapp.generated.resources.sign_in_to_nsec +import mantra.composeapp.generated.resources.sign_in_with_an_npub +import mantra.composeapp.generated.resources.something_went_wrong_and_we_were_unable_to +import mantra.composeapp.generated.resources.this_will_give_you_read_only_access_to_the +import mantra.composeapp.generated.resources.this_will_give_you_write_access_to_the @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -63,7 +75,7 @@ fun SignInToProfileScreen( when (val signInToProfileUIState = signInToProfileViewModel.signInToProfileUIState.value) { is press.mantra.compose.ui.view.state.SignInToProfileUIState.InputPrompt -> { Text( - "Sign in", + stringResource(Res.string.sign_in), style = MaterialTheme.typography.headlineSmall ) @@ -87,13 +99,13 @@ fun SignInToProfileScreen( ), label = { Text( - text = "nsec, npub, nip-05 (static address)", + text = stringResource(Res.string.nsec_npub_nip_05_static_address), maxLines = 1, ) }, placeholder = { Text( - text = "Enter the nsec or npub (read only) that you want to sign in as", + text = stringResource(Res.string.enter_the_nsec_or_npub_read_only_that_you), maxLines = 1, ) }, @@ -129,7 +141,7 @@ fun SignInToProfileScreen( }, ) { Text( - "Next" + stringResource(Res.string.next) ) Icon( Icons.Default.NavigateNext, @@ -144,7 +156,7 @@ fun SignInToProfileScreen( modifier = Modifier.weight(1f) ) Text( - text = "Sign in with an npub", + text = stringResource(Res.string.sign_in_with_an_npub), style = MaterialTheme.typography.headlineMedium ) @@ -168,7 +180,7 @@ fun SignInToProfileScreen( Text( - text = "This will give you read only access to the profile.", + text = stringResource(Res.string.this_will_give_you_read_only_access_to_the), style = MaterialTheme.typography.labelSmall, textAlign = TextAlign.Center ) @@ -184,7 +196,7 @@ fun SignInToProfileScreen( } ) { Text( - text = "Sign in" + text = stringResource(Res.string.sign_in) ) } } @@ -196,12 +208,12 @@ fun SignInToProfileScreen( modifier = Modifier.weight(1f) ) Text( - text = "Sign in to nsec", + text = stringResource(Res.string.sign_in_to_nsec), style = MaterialTheme.typography.headlineMedium ) Text( - text = "Be sure to keep this nsec safe.", + text = stringResource(Res.string.be_sure_to_keep_this_nsec_safe), textAlign = TextAlign.Center, style = MaterialTheme.typography.bodyMedium ) @@ -214,7 +226,7 @@ fun SignInToProfileScreen( Text( - text = "This will give you write access to the profile.", + text = stringResource(Res.string.this_will_give_you_write_access_to_the), style = MaterialTheme.typography.labelSmall, textAlign = TextAlign.Center ) @@ -230,7 +242,7 @@ fun SignInToProfileScreen( } ) { Text( - text = "Sign in" + text = stringResource(Res.string.sign_in) ) } } @@ -241,7 +253,7 @@ fun SignInToProfileScreen( modifier = Modifier.weight(1f) ) Text( - text = "Something went wrong and we were unable to sign in to your provided profile. Please try again later.", + text = stringResource(Res.string.something_went_wrong_and_we_were_unable_to), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SocialPreconditionScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SocialPreconditionScreen.kt index a4d20fb4..6f2f75a1 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SocialPreconditionScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SocialPreconditionScreen.kt @@ -23,6 +23,14 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.invite_a_friend +import mantra.composeapp.generated.resources.skip_for_now +import mantra.composeapp.generated.resources.tell_friends_to_join_you_so_your_feed_stays +import mantra.composeapp.generated.resources.view_and_accept_invites_you_may_have +import mantra.composeapp.generated.resources.view_invites +import mantra.composeapp.generated.resources.who_will_you_be_passing_the_aux_to @Composable fun SocialPreconditionScreen( @@ -47,7 +55,7 @@ fun SocialPreconditionScreen( ) }, text = { - Text("Skip for now") + Text(stringResource(Res.string.skip_for_now)) }, onClick = { onNavigateToSkipForNow.invoke() @@ -67,7 +75,7 @@ fun SocialPreconditionScreen( ) { Text( - "Who will you be passing the aux to?", + stringResource(Res.string.who_will_you_be_passing_the_aux_to), textAlign = TextAlign.Center, style = MaterialTheme.typography.titleLarge ) @@ -77,7 +85,7 @@ fun SocialPreconditionScreen( ) Text( - "Tell friends to join you so your feed stays lively and fresh.", + stringResource(Res.string.tell_friends_to_join_you_so_your_feed_stays), textAlign = TextAlign.Center ) @@ -87,7 +95,7 @@ fun SocialPreconditionScreen( } ) { Text( - "Invite a friend" + stringResource(Res.string.invite_a_friend) ) } @@ -96,7 +104,7 @@ fun SocialPreconditionScreen( ) Text( - "View and accept invites you may have received to stay connected with others.", + stringResource(Res.string.view_and_accept_invites_you_may_have), textAlign = TextAlign.Center ) @@ -105,7 +113,7 @@ fun SocialPreconditionScreen( onNavigateToViewInvites.invoke() } ) { - Text("View invites") + Text(stringResource(Res.string.view_invites)) } } } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SovereignWalletStartupScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SovereignWalletStartupScreen.kt index 3dd8a638..02d664d9 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SovereignWalletStartupScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SovereignWalletStartupScreen.kt @@ -27,6 +27,11 @@ import fr.acinq.phoenix.utils.preferences.UserWalletMetadata import fr.acinq.phoenix.utils.preferences.getByWalletIdOrDefault import kotlinx.coroutines.flow.first import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.lock_prompt_coming_soon +import mantra.composeapp.generated.resources.select_a_wallet +import mantra.composeapp.generated.resources.startup_error @Composable fun SovereignWalletStartupScreen( @@ -135,7 +140,7 @@ fun SovereignWalletStartupScreen( topContent = { Spacer(Modifier.height(MaterialTheme.spacing.space800)) Text( - text = "Select a wallet", + text = stringResource(Res.string.select_a_wallet), style = MaterialTheme.typography.headlineSmall ) Spacer(Modifier.height(MaterialTheme.spacing.space200)) @@ -191,7 +196,7 @@ fun SovereignWalletStartupScreen( Column(horizontalAlignment = Alignment.CenterHorizontally) { Text( - text = "Startup error" + text = stringResource(Res.string.startup_error) ) when (startupState) { @@ -280,7 +285,7 @@ private fun BoxScope.ScreenLockPrompt( goToWalletSelector: (() -> Unit)?, ) { Text( - text = "Lock prompt coming soon.", + text = stringResource(Res.string.lock_prompt_coming_soon), ) // val scope = rememberCoroutineScope() // diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslateChunkScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslateChunkScreen.kt index 15826db4..5d05cf60 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslateChunkScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslateChunkScreen.kt @@ -54,6 +54,14 @@ import press.mantra.compose.ui.theme.TorchTheme import press.mantra.compose.ui.view.model.TranslateChunkViewModel import press.mantra.compose.ui.view.state.TranslateChunkUIState import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.enter_the_translation_for_this_chunk +import mantra.composeapp.generated.resources.original +import mantra.composeapp.generated.resources.propose_translation +import mantra.composeapp.generated.resources.translate_chunk +import mantra.composeapp.generated.resources.translated_text +import mantra.composeapp.generated.resources.translation @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -109,7 +117,7 @@ fun TranslateChunkScreen( modifier = Modifier.imePadding(), topBar = { TopAppBar( - title = { Text("Translate chunk") }, + title = { Text(stringResource(Res.string.translate_chunk)) }, navigationIcon = { IconButton(onClick = onNavigateBack) { Icon( @@ -177,7 +185,7 @@ fun TranslateChunkScreen( Icons.Default.Add, contentDescription = "Propose translation" ) - Text("Propose translation") + Text(stringResource(Res.string.propose_translation)) } } ) @@ -201,7 +209,7 @@ fun TranslateChunkScreen( } Text( - text = "Original", + text = stringResource(Res.string.original), style = MaterialTheme.typography.labelMedium ) Card { @@ -213,14 +221,14 @@ fun TranslateChunkScreen( } Text( - text = "Translation", + text = stringResource(Res.string.translation), style = MaterialTheme.typography.labelMedium ) OutlinedTextField( modifier = Modifier.fillMaxWidth(), state = translationFieldState, - label = { Text("Translated text") }, - placeholder = { Text("Enter the translation for this chunk") }, + label = { Text(stringResource(Res.string.translated_text)) }, + placeholder = { Text(stringResource(Res.string.enter_the_translation_for_this_chunk)) }, ) } } @@ -234,7 +242,7 @@ fun TranslateChunkScreen( ) { Spacer(modifier = Modifier.weight(1f)) Text( - text = "Translate chunk", + text = stringResource(Res.string.translate_chunk), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslationArtifactVersionDetailScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslationArtifactVersionDetailScreen.kt index 7d72bf70..9dacc18e 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslationArtifactVersionDetailScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslationArtifactVersionDetailScreen.kt @@ -47,6 +47,14 @@ import press.mantra.compose.ui.theme.TorchTheme import press.mantra.compose.ui.view.model.TranslationArtifactVersionDetailViewModel import press.mantra.compose.ui.view.state.TranslationArtifactVersionDetailUIState import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.chapters +import mantra.composeapp.generated.resources.details +import mantra.composeapp.generated.resources.no_chapters +import mantra.composeapp.generated.resources.propose +import mantra.composeapp.generated.resources.this_group_has_no_shared_key_so_it_cannot +import mantra.composeapp.generated.resources.translation_detail @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -134,7 +142,7 @@ fun TranslationArtifactVersionDetailScreen( supportingContent = { Text( if (!translationDetailUIState.canSign) { - "This group has no shared key, so it cannot sign them in." + stringResource(Res.string.this_group_has_no_shared_key_so_it_cannot) } else { "They were signed into the artifact after this " + "translation. Ask the group to add them so they " + @@ -166,7 +174,7 @@ fun TranslationArtifactVersionDetailScreen( ) } ) { - Text("Propose") + Text(stringResource(Res.string.propose)) } } ) @@ -179,12 +187,12 @@ fun TranslationArtifactVersionDetailScreen( // Chapters with translation progress item { Text( - text = "Chapters", + text = stringResource(Res.string.chapters), style = MaterialTheme.typography.labelMedium ) } if (translationDetailUIState.chapters.isEmpty()) { - item { Text("No chapters.") } + item { Text(stringResource(Res.string.no_chapters)) } } else { items( items = translationDetailUIState.chapters, @@ -223,7 +231,7 @@ fun TranslationArtifactVersionDetailScreen( // Details item { Text( - text = "Details", + text = stringResource(Res.string.details), style = MaterialTheme.typography.labelMedium ) } @@ -250,7 +258,7 @@ fun TranslationArtifactVersionDetailScreen( ) { Spacer(modifier = Modifier.weight(1f)) Text( - text = "Translation detail", + text = stringResource(Res.string.translation_detail), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslationChapterScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslationChapterScreen.kt index 40eede45..6f74e5e7 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslationChapterScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslationChapterScreen.kt @@ -48,6 +48,10 @@ import press.mantra.compose.ui.view.model.TranslationChapterViewModel import press.mantra.compose.ui.view.state.ChunkTranslationPair import press.mantra.compose.ui.view.state.TranslationChapterUIState import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.chapter_translation +import mantra.composeapp.generated.resources.this_chapter_has_no_chunks @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -87,7 +91,7 @@ fun TranslationChapterScreen( Scaffold( topBar = { TopAppBar( - title = { Text("Chapter translation") }, + title = { Text(stringResource(Res.string.chapter_translation)) }, navigationIcon = { IconButton(onClick = onNavigateBack) { Icon( @@ -127,7 +131,7 @@ fun TranslationChapterScreen( modifier = Modifier.fillMaxWidth().padding(MaterialTheme.spacing.containerPadding), contentAlignment = Alignment.Center ) { - Text("This chapter has no chunks.") + Text(stringResource(Res.string.this_chapter_has_no_chunks)) } } } else { @@ -164,7 +168,7 @@ fun TranslationChapterScreen( ) { Spacer(modifier = Modifier.weight(1f)) Text( - text = "Chapter translation", + text = stringResource(Res.string.chapter_translation), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnannouncedProfileScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnannouncedProfileScreen.kt index d267f811..408d55bd 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnannouncedProfileScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnannouncedProfileScreen.kt @@ -18,6 +18,10 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.everything_is_cryptographical_sound_just +import mantra.composeapp.generated.resources.torch_will_be_broadcast_what_you_publish_to @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -39,13 +43,13 @@ fun UnannouncedProfileScreen() { modifier = Modifier.weight(1f) ) Text( - text = "Everything is cryptographical sound. Just announcing your profile to the world.", + text = stringResource(Res.string.everything_is_cryptographical_sound_just), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) Text( - text = "Torch will be broadcast what you publish to a distributed set of relays so that it's decentralized.", + text = stringResource(Res.string.torch_will_be_broadcast_what_you_publish_to), style = MaterialTheme.typography.bodySmall, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnindexedProfileScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnindexedProfileScreen.kt index eecf6676..ef3d18cf 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnindexedProfileScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnindexedProfileScreen.kt @@ -18,6 +18,10 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.events_are_indexed_so_that_we_can_deliver_a +import mantra.composeapp.generated.resources.everything_is_cryptographical_sound_just_2 @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -39,13 +43,13 @@ fun UnindexedProfileScreen() { modifier = Modifier.weight(1f) ) Text( - text = "Everything is cryptographical sound. Just indexing your profile on the device.", + text = stringResource(Res.string.everything_is_cryptographical_sound_just_2), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) Text( - text = "Events are indexed so that we can deliver a premium local first experience.", + text = stringResource(Res.string.events_are_indexed_so_that_we_can_deliver_a), style = MaterialTheme.typography.bodySmall, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnqueuedProfileScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnqueuedProfileScreen.kt index 6222d9a5..92e99bb6 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnqueuedProfileScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnqueuedProfileScreen.kt @@ -18,6 +18,10 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.all_broadcasts_are_queued_so_that_we_can +import mantra.composeapp.generated.resources.everything_is_cryptographical_sound_just_3 @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -39,13 +43,13 @@ fun UnqueuedProfileScreen() { modifier = Modifier.weight(1f) ) Text( - text = "Everything is cryptographical sound. Just need to queue your profile and announce it to the world.", + text = stringResource(Res.string.everything_is_cryptographical_sound_just_3), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) Text( - text = "All broadcasts are queued so that we can manage data usage on metered connections.", + text = stringResource(Res.string.all_broadcasts_are_queued_so_that_we_can), style = MaterialTheme.typography.bodySmall, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnqueuedProfileSynchronizationScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnqueuedProfileSynchronizationScreen.kt index 56504446..832ae60b 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnqueuedProfileSynchronizationScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnqueuedProfileSynchronizationScreen.kt @@ -20,6 +20,10 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.we_are_looking_for_your_profile_on_as_many +import mantra.composeapp.generated.resources.we_are_searching_the_internet_to_find_your @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -53,13 +57,13 @@ fun UnqueuedProfileSynchronizationScreen( modifier = Modifier.weight(1f) ) Text( - text = "We are searching the internet to find your profile and complete sign in.", + text = stringResource(Res.string.we_are_searching_the_internet_to_find_your), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) Text( - text = "We are looking for your profile on as many relays as possible. Nostr aims to be decentralized by distributing data to multiple nodse.", + text = stringResource(Res.string.we_are_looking_for_your_profile_on_as_many), style = MaterialTheme.typography.bodySmall, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnsignedProfileScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnsignedProfileScreen.kt index a9d58335..a25a79d4 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnsignedProfileScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnsignedProfileScreen.kt @@ -18,6 +18,10 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.as_long_as_you_control_your_keys_there_can +import mantra.composeapp.generated.resources.your_profile_is_almost_ready_just_getting_it @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -39,13 +43,13 @@ fun UnsignedProfileScreen() { modifier = Modifier.weight(1f) ) Text( - text = "Your profile is almost ready... just getting it's first cryptographic signature together.", + text = stringResource(Res.string.your_profile_is_almost_ready_just_getting_it), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) Text( - text = "As long as you control your keys there can be no dispute about who YOU actually is.", + text = stringResource(Res.string.as_long_as_you_control_your_keys_there_can), style = MaterialTheme.typography.bodySmall, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnsyncedProfileScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnsyncedProfileScreen.kt index 7ff41c7d..2ad93668 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnsyncedProfileScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/UnsyncedProfileScreen.kt @@ -18,6 +18,10 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.we_are_looking_for_your_profile_on_as_many +import mantra.composeapp.generated.resources.we_are_searching_the_internet_to_find_your @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -41,13 +45,13 @@ fun UnsyncedProfileScreen( modifier = Modifier.weight(1f) ) Text( - text = "We are searching the internet to find your profile and complete sign in.", + text = stringResource(Res.string.we_are_searching_the_internet_to_find_your), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) Text( - text = "We are looking for your profile on as many relays as possible. Nostr aims to be decentralized by distributing data to multiple nodse.", + text = stringResource(Res.string.we_are_looking_for_your_profile_on_as_many), style = MaterialTheme.typography.bodySmall, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/WriteNewNoteScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/WriteNewNoteScreen.kt index cfb5a817..8a6469b4 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/WriteNewNoteScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/WriteNewNoteScreen.kt @@ -45,6 +45,16 @@ import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent import kotlin.time.Clock import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.next +import mantra.composeapp.generated.resources.something_went_wrong_and_we_were_unable_to_3 +import mantra.composeapp.generated.resources.the_above_will_be_your_new_note +import mantra.composeapp.generated.resources.transmit_note +import mantra.composeapp.generated.resources.type_out_what_you_would_like_to_publish +import mantra.composeapp.generated.resources.what_s_your_comment_on_the_below +import mantra.composeapp.generated.resources.what_s_your_reply_to_the_above +import mantra.composeapp.generated.resources.what_vibrations_do_you_want_to_send_out @OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalFoundationApi::class) @Composable @@ -148,18 +158,18 @@ fun WriteNewNoteScreen( label = { Text( text = if (writeNewNoteUIState.inReplyToNostrEvent != null) { - "What's your reply to the above" + stringResource(Res.string.what_s_your_reply_to_the_above) } else if (writeNewNoteUIState.quotedNostrEvent != null) { - "What's your comment on the below" + stringResource(Res.string.what_s_your_comment_on_the_below) } else { - "What vibrations do you want to send out?" + stringResource(Res.string.what_vibrations_do_you_want_to_send_out) }, maxLines = 1, ) }, placeholder = { Text( - text = "Type out what you would like to publish", + text = stringResource(Res.string.type_out_what_you_would_like_to_publish), maxLines = 1, ) }, @@ -271,7 +281,7 @@ fun WriteNewNoteScreen( }, ) { Text( - "Next" + stringResource(Res.string.next) ) Icon( Icons.Default.NavigateNext, @@ -399,7 +409,7 @@ fun WriteNewNoteScreen( } Text( - text = "The above will be your new note.", + text = stringResource(Res.string.the_above_will_be_your_new_note), style = MaterialTheme.typography.bodySmall ) @@ -419,7 +429,7 @@ fun WriteNewNoteScreen( } ) { Text( - text = "Transmit note" + text = stringResource(Res.string.transmit_note) ) } } @@ -430,7 +440,7 @@ fun WriteNewNoteScreen( modifier = Modifier.weight(1f) ) Text( - text = "Something went wrong and we were unable to write a new note. Please try again later.", + text = stringResource(Res.string.something_went_wrong_and_we_were_unable_to_3), style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/ArticleCard.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/ArticleCard.kt index 89cbf02f..ae095edf 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/ArticleCard.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/ArticleCard.kt @@ -22,6 +22,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.article +import mantra.composeapp.generated.resources.loading_article +import mantra.composeapp.generated.resources.untitled_article @Composable private fun ArticleCard( @@ -71,7 +76,7 @@ private fun ArticleCard( ) Spacer(Modifier.width(MaterialTheme.spacing.space100)) Text( - text = "Loading article...", + text = stringResource(Res.string.loading_article), style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant ) @@ -99,14 +104,14 @@ private fun ArticleCard( modifier = Modifier.padding(end = MaterialTheme.spacing.compactPadding) ) { Text( - text = "ARTICLE", + text = stringResource(Res.string.article), style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onPrimaryContainer, modifier = Modifier.padding(horizontal = MaterialTheme.spacing.space75, vertical = MaterialTheme.spacing.space25) ) } Text( - text = title ?: "Untitled article", + text = title ?: stringResource(Res.string.untitled_article), style = MaterialTheme.typography.titleSmall, color = MaterialTheme.colorScheme.onSurface, maxLines = 2, diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/ImageWithContextMenu.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/ImageWithContextMenu.kt index 7423711c..6cb28994 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/ImageWithContextMenu.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/ImageWithContextMenu.kt @@ -33,6 +33,11 @@ import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.unit.dp import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.copy_url +import mantra.composeapp.generated.resources.download +import mantra.composeapp.generated.resources.tap_to_load @OptIn(ExperimentalFoundationApi::class) @Composable @@ -67,7 +72,7 @@ internal fun ImageWithContextMenu(meta: MediaMeta, onFullScreen: () -> Unit) { ) Spacer(Modifier.height(MaterialTheme.spacing.space100)) Text( - "Tap to load", + stringResource(Res.string.tap_to_load), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant ) @@ -95,14 +100,14 @@ internal fun ImageWithContextMenu(meta: MediaMeta, onFullScreen: () -> Unit) { onDismissRequest = { showMenu = false } ) { DropdownMenuItem( - text = { Text("Copy URL") }, + text = { Text(stringResource(Res.string.copy_url)) }, onClick = { clipboardManager.setText(AnnotatedString(url)) showMenu = false } ) DropdownMenuItem( - text = { Text("Download") }, + text = { Text(stringResource(Res.string.download)) }, onClick = { showMenu = false // scope.launch { MediaDownloader.downloadMedia(context, url) } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/LightningInvoiceCard.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/LightningInvoiceCard.kt index 83739e03..0f76c3d6 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/LightningInvoiceCard.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/LightningInvoiceCard.kt @@ -35,6 +35,16 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.launch import press.mantra.compose.ui.theme.spacing import press.mantra.compose.ui.composable.widgets.Decorative +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.any_amount +import mantra.composeapp.generated.resources.cancel +import mantra.composeapp.generated.resources.expired +import mantra.composeapp.generated.resources.failed +import mantra.composeapp.generated.resources.lightning_invoice +import mantra.composeapp.generated.resources.paid +import mantra.composeapp.generated.resources.pay +import mantra.composeapp.generated.resources.pay_now @Composable internal fun LightningInvoiceCard( @@ -52,7 +62,7 @@ internal fun LightningInvoiceCard( if (showConfirm) { AlertDialog( onDismissRequest = { showConfirm = false }, - title = { Text("Lightning invoice") }, + title = { Text(stringResource(Res.string.lightning_invoice)) }, text = { Column { Text( @@ -86,11 +96,11 @@ internal fun LightningInvoiceCard( containerColor = primary, contentColor = onPrimary ) - ) { Text("Pay") } + ) { Text(stringResource(Res.string.pay)) } }, dismissButton = { TextButton(onClick = { showConfirm = false }) { - Text("Cancel") + Text(stringResource(Res.string.cancel)) } } ) @@ -119,7 +129,7 @@ internal fun LightningInvoiceCard( Text( text = if (decoded.amount != null) "${decoded.amount!!.truncateToSatoshi()}" - else "Any amount", + else stringResource(Res.string.any_amount), style = MaterialTheme.typography.titleSmall, color = primary ) @@ -133,7 +143,7 @@ internal fun LightningInvoiceCard( } if (isExpired) { Text( - text = "Expired", + text = stringResource(Res.string.expired), style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.error ) @@ -148,12 +158,12 @@ internal fun LightningInvoiceCard( strokeWidth = 2.dp ) InvoicePayState.Success -> Text( - text = "✓ Paid", + text = stringResource(Res.string.paid), style = MaterialTheme.typography.labelMedium, color = primary ) InvoicePayState.Failed -> Text( - text = "✗ Failed", + text = stringResource(Res.string.failed), style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.error ) @@ -166,8 +176,8 @@ internal fun LightningInvoiceCard( ) ) { Text( - if (isExpired) "Expired" - else "Pay now" + if (isExpired) stringResource(Res.string.expired) + else stringResource(Res.string.pay_now) ) } } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/LiveStreamCardContent.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/LiveStreamCardContent.kt index af8f3235..6b4f135f 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/LiveStreamCardContent.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/LiveStreamCardContent.kt @@ -20,6 +20,12 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.ended +import mantra.composeapp.generated.resources.live +import mantra.composeapp.generated.resources.live_stream +import mantra.composeapp.generated.resources.loading_stream @Composable internal fun LiveStreamCardContent( @@ -45,7 +51,7 @@ internal fun LiveStreamCardContent( ) Spacer(Modifier.width(MaterialTheme.spacing.space100)) Text( - text = "Loading stream...", + text = stringResource(Res.string.loading_stream), style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant ) @@ -92,7 +98,7 @@ internal fun LiveStreamCardContent( modifier = Modifier.padding(end = MaterialTheme.spacing.compactPadding) ) { Text( - text = "LIVE", + text = stringResource(Res.string.live), style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onError, modifier = Modifier.padding(horizontal = MaterialTheme.spacing.space75, vertical = MaterialTheme.spacing.space25) @@ -105,7 +111,7 @@ internal fun LiveStreamCardContent( modifier = Modifier.padding(end = MaterialTheme.spacing.compactPadding) ) { Text( - text = "ENDED", + text = stringResource(Res.string.ended), style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.padding(horizontal = MaterialTheme.spacing.space75, vertical = MaterialTheme.spacing.space25) @@ -113,7 +119,7 @@ internal fun LiveStreamCardContent( } } Text( - text = title ?: "Live stream", + text = title ?: stringResource(Res.string.live_stream), style = MaterialTheme.typography.titleSmall, color = MaterialTheme.colorScheme.onSurface, maxLines = 2, diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/QuotedAddressableNote.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/QuotedAddressableNote.kt index d0c16d3c..5bbafff5 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/QuotedAddressableNote.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/QuotedAddressableNote.kt @@ -18,6 +18,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.dp import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.loading_note @Composable @@ -64,7 +67,7 @@ internal fun QuotedAddressableNote( ) Spacer(Modifier.width(MaterialTheme.spacing.space100)) Text( - text = "Loading note...", + text = stringResource(Res.string.loading_note), style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/QuotedNote.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/QuotedNote.kt index 39eef02b..efc96562 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/QuotedNote.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/QuotedNote.kt @@ -21,6 +21,9 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.vitorpamplona.quartz.nip01Core.core.HexKey import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.loading_note @Composable fun QuotedNote( @@ -105,7 +108,7 @@ fun QuotedNote( ) Spacer(Modifier.width(MaterialTheme.spacing.space100)) Text( - text = "Loading note...", + text = stringResource(Res.string.loading_note), style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/UnsupportedKindBadge.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/UnsupportedKindBadge.kt index 870f9588..95410c3c 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/UnsupportedKindBadge.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/UnsupportedKindBadge.kt @@ -12,6 +12,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.dp import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.unsupported_event_kind @Composable internal fun UnsupportedKindBadge(kind: Int?, style: TextStyle) { @@ -24,7 +27,7 @@ internal fun UnsupportedKindBadge(kind: Int?, style: TextStyle) { .padding(vertical = MaterialTheme.spacing.space75) ) { Text( - text = if (kind != null) "Unsupported event kind: $kind" else "Unsupported event kind", + text = if (kind != null) "Unsupported event kind: $kind" else stringResource(Res.string.unsupported_event_kind), style = style, color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.padding(MaterialTheme.spacing.space175) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/detail/MetadataEventDetail.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/detail/MetadataEventDetail.kt index a04d24cd..9952f93f 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/detail/MetadataEventDetail.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/detail/MetadataEventDetail.kt @@ -58,6 +58,15 @@ import press.mantra.compose.ui.view.state.MetadataEventDetailUIState import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.add_to_group +import mantra.composeapp.generated.resources.block_user +import mantra.composeapp.generated.resources.edit_profile +import mantra.composeapp.generated.resources.follow +import mantra.composeapp.generated.resources.follow_back +import mantra.composeapp.generated.resources.send_message +import mantra.composeapp.generated.resources.unfollow @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -181,7 +190,7 @@ fun MetadataEventDetail( onClick = onNavigateToEditProfile ) { Text( - "Edit profile" + stringResource(Res.string.edit_profile) ) } @@ -195,7 +204,7 @@ fun MetadataEventDetail( } ) { Text( - "Unfollow" + stringResource(Res.string.unfollow) ) } } else { @@ -207,9 +216,9 @@ fun MetadataEventDetail( ) { Text( text = if (metadataEventDetailUIState.followingActiveUserConnection != null) { - "follow back" + stringResource(Res.string.follow_back) } else { - "follow" + stringResource(Res.string.follow) } ) } @@ -252,7 +261,7 @@ fun MetadataEventDetail( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Add to group") + Text(stringResource(Res.string.add_to_group)) } } @@ -273,7 +282,7 @@ fun MetadataEventDetail( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Block user") + Text(stringResource(Res.string.block_user)) } } @@ -297,7 +306,7 @@ fun MetadataEventDetail( Spacer( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Send message") + Text(stringResource(Res.string.send_message)) } } } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/detail/TextNoteEventDetail.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/detail/TextNoteEventDetail.kt index 2a8aaac6..720ea55e 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/detail/TextNoteEventDetail.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/detail/TextNoteEventDetail.kt @@ -49,6 +49,11 @@ import press.mantra.compose.extensions.toFormattedTimeAndDateString import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.be_the_first_to_comment +import mantra.composeapp.generated.resources.post +import mantra.composeapp.generated.resources.something_went_wrong @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -87,7 +92,7 @@ fun TextNoteEventDetail( } }, title = { - Text("Post") + Text(stringResource(Res.string.post)) }, ) }, @@ -346,7 +351,7 @@ fun TextNoteEventDetail( if (inReplyToFeedListUIState.localNostrEvents.isEmpty()) { item { Text( - "Be the first to comment." + stringResource(Res.string.be_the_first_to_comment) ) } } else { @@ -363,7 +368,7 @@ fun TextNoteEventDetail( press.mantra.compose.ui.view.state.FeedListUIState.Error -> { item { Text( - text = "Something went wrong" + text = stringResource(Res.string.something_went_wrong) ) } } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/dialogs/NewChatBottomSheetDialog.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/dialogs/NewChatBottomSheetDialog.kt index 924593f7..f2520e36 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/dialogs/NewChatBottomSheetDialog.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/dialogs/NewChatBottomSheetDialog.kt @@ -29,6 +29,12 @@ import press.mantra.compose.ui.composable.navigation.routes.Route import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.close +import mantra.composeapp.generated.resources.create_new_chat +import mantra.composeapp.generated.resources.direct_message_via_npub +import mantra.composeapp.generated.resources.start_a_group_chat @OptIn(ExperimentalMaterial3Api::class) @@ -55,7 +61,7 @@ fun NewChatBottomSheetDialog( horizontalAlignment = Alignment.CenterHorizontally ) { Text( - text = "Create new chat", + text = stringResource(Res.string.create_new_chat), textAlign = TextAlign.Center, style = MaterialTheme.typography.bodyLarge ) @@ -74,7 +80,7 @@ fun NewChatBottomSheetDialog( ) }, headlineContent = { - Text("Direct message via npub") + Text(stringResource(Res.string.direct_message_via_npub)) }, trailingContent = { Icon( @@ -101,7 +107,7 @@ fun NewChatBottomSheetDialog( }, headlineContent = { Text( - text = "Start a group chat" + text = stringResource(Res.string.start_a_group_chat) ) }, trailingContent = { @@ -129,7 +135,7 @@ fun NewChatBottomSheetDialog( Spacer( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Close") + Text(stringResource(Res.string.close)) } } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/dialogs/StartDirectMessageToNpubOrNip05Dialog.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/dialogs/StartDirectMessageToNpubOrNip05Dialog.kt index a3cdc745..17fb12c1 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/dialogs/StartDirectMessageToNpubOrNip05Dialog.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/dialogs/StartDirectMessageToNpubOrNip05Dialog.kt @@ -46,6 +46,11 @@ import press.mantra.compose.ui.theme.spacing import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.input_npub_or_nip05 +import mantra.composeapp.generated.resources.start_chat +import mantra.composeapp.generated.resources.start_chat_via_npub_or_nip05 @Composable fun StartDirectMessageToNpubOrNip05Dialog( @@ -91,7 +96,7 @@ fun StartDirectMessageToNpubOrNip05Dialog( modifier = Modifier.fillMaxWidth().padding( horizontal = MaterialTheme.spacing.space250, ), - text = "Start chat via npub or nip05", + text = stringResource(Res.string.start_chat_via_npub_or_nip05), style = MaterialTheme.typography.labelMedium, textAlign = TextAlign.Center ) @@ -99,7 +104,7 @@ fun StartDirectMessageToNpubOrNip05Dialog( modifier = Modifier.focusRequester(npubFieldFocus), state = textFieldState, placeholder = { - Text("Input npub... or nip05") + Text(stringResource(Res.string.input_npub_or_nip05)) }, trailingIcon = { IconButton( @@ -166,7 +171,7 @@ fun StartDirectMessageToNpubOrNip05Dialog( } } ) { - Text("Start chat") + Text(stringResource(Res.string.start_chat)) Spacer( modifier = Modifier.width(MaterialTheme.spacing.space125) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/feed/EventListView.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/feed/EventListView.kt index ea28444a..d72ea62b 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/feed/EventListView.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/feed/EventListView.kt @@ -25,6 +25,11 @@ import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent import com.vitorpamplona.quartz.nip18Reposts.RepostEvent import kotlin.time.Instant import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.loading_author_information_2 +import mantra.composeapp.generated.resources.malformed_note +import mantra.composeapp.generated.resources.reposted @Composable fun press.mantra.compose.database.model.intermdiate.LocalNostrEvent.ListView( @@ -66,7 +71,7 @@ fun press.mantra.compose.database.model.intermdiate.LocalNostrEvent.ListView( color = press.mantra.compose.ui.composable.widgets.profile.ProfileColor.fromPublicKey(profile?.publicKey ?: nostrEvent.pubKey) ) Text( - text = "reposted", + text = stringResource(Res.string.reposted), style = MaterialTheme.typography.labelSmall ) } @@ -92,7 +97,7 @@ fun press.mantra.compose.database.model.intermdiate.LocalNostrEvent.ListView( ).containedPost() if (containedPost != null) { - Text("Loading author information...") + Text(stringResource(Res.string.loading_author_information_2)) Text( containedPost.content ) @@ -100,7 +105,7 @@ fun press.mantra.compose.database.model.intermdiate.LocalNostrEvent.ListView( text = Instant.fromEpochSeconds(containedPost.createdAt).toFormattedTimeAndDateString() ) } else { - Text("Malformed note") + Text(stringResource(Res.string.malformed_note)) } } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/feed/TextNoteFeedItem.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/feed/TextNoteFeedItem.kt index 822e5d4b..03113927 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/feed/TextNoteFeedItem.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/feed/TextNoteFeedItem.kt @@ -26,6 +26,10 @@ import androidx.compose.ui.unit.dp import press.mantra.compose.extensions.toFormattedTimeAndDateString import com.vitorpamplona.quartz.nip01Core.core.HexKey import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.loading_author_information +import mantra.composeapp.generated.resources.loading_information @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -63,7 +67,7 @@ internal fun TextNoteFeedItem( ), style = MaterialTheme.typography.labelLargeEmphasized, color = press.mantra.compose.ui.composable.widgets.profile.ProfileColor.fromPublicKey(localInReplyToNostrEvent.nostrEvent.pubKey), - text = localInReplyToNostrEvent.profile?.humanReadableNameOrPubkey() ?: "loading information..." + text = localInReplyToNostrEvent.profile?.humanReadableNameOrPubkey() ?: stringResource(Res.string.loading_information) ) } } @@ -116,7 +120,7 @@ internal fun TextNoteFeedItem( } } else { Text( - text = "Loading author information" + text = stringResource(Res.string.loading_author_information) ) } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/ChatMessageListViewModel.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/ChatMessageListViewModel.kt index e8a53e83..231908ea 100755 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/ChatMessageListViewModel.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/ChatMessageListViewModel.kt @@ -94,6 +94,16 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.launch import press.mantra.compose.ui.theme.spacing import press.mantra.compose.ui.composable.widgets.Decorative +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.currently_no_messages_have_been_shared +import mantra.composeapp.generated.resources.loading +import mantra.composeapp.generated.resources.no_chat_message_relays_were_found_for_this +import mantra.composeapp.generated.resources.private_to_you +import mantra.composeapp.generated.resources.review +import mantra.composeapp.generated.resources.something_went_wrong +import mantra.composeapp.generated.resources.waiting_for_your_signature +import mantra.composeapp.generated.resources.you class ChatMessageListViewModel( initialChatMessageListUIState: ChatMessageListUIState, @@ -399,7 +409,7 @@ class ChatMessageListViewModel( modifier = Modifier.height(MaterialTheme.spacing.space600) ) Text( - text = "Something went wrong", + text = stringResource(Res.string.something_went_wrong), ) } } @@ -420,7 +430,7 @@ class ChatMessageListViewModel( ) Text( modifier = Modifier.padding(MaterialTheme.spacing.space250), - text = "Currently no messages have been shared.\nBreak the ice.", + text = stringResource(Res.string.currently_no_messages_have_been_shared), textAlign = TextAlign.Center ) @@ -489,7 +499,7 @@ class ChatMessageListViewModel( modifier = Modifier.weight(1f) ) { Text( - text = "No chat message relays were found for this user.", + text = stringResource(Res.string.no_chat_message_relays_were_found_for_this), textAlign = TextAlign.Center, style = MaterialTheme.typography.labelSmall ) @@ -660,7 +670,7 @@ class ChatMessageListViewModel( text = if (localChatMessage.chatMessage.isUserMessage) { "Private to ${nameFor(localChatMessage.chatMessage.directMessageRecipientPublicKey)}" } else { - "Private to you" + stringResource(Res.string.private_to_you) }, color = MaterialTheme.colorScheme.primary, style = MaterialTheme.typography.labelSmall @@ -750,7 +760,7 @@ class ChatMessageListViewModel( modifier = Modifier.height(MaterialTheme.spacing.space600) ) Text( - text = "Loading", + text = stringResource(Res.string.loading), textAlign = TextAlign.Center ) Spacer( @@ -875,7 +885,7 @@ private fun ProposalsAwaitingYouNotice( ) { Text( text = if (single != null) { - "Waiting for your signature" + stringResource(Res.string.waiting_for_your_signature) } else { "${proposals.size} proposals are waiting for your signature" }, @@ -896,7 +906,7 @@ private fun ProposalsAwaitingYouNotice( // thing, so a member reading down the room is not asked twice in two // vocabularies. Text( - text = "Review", + text = stringResource(Res.string.review), style = MaterialTheme.typography.labelLarge ) @@ -1062,7 +1072,7 @@ private fun RitualNotice( ) { append( if (chatMessage.isUserMessage) { - "You" + stringResource(Res.string.you) } else { localChatMessage.profile?.humanReadableNameOrPubkey() ?: chatMessage.senderPublicKey.shortened() @@ -1087,7 +1097,7 @@ private fun RitualNotice( if (isRequest) { Text( - text = "Review", + text = stringResource(Res.string.review), style = MaterialTheme.typography.labelLarge, color = MaterialTheme.colorScheme.primary ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/ChatRoomListViewModel.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/ChatRoomListViewModel.kt index 61e99403..a407647b 100755 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/ChatRoomListViewModel.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/ChatRoomListViewModel.kt @@ -41,6 +41,11 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.IO import kotlinx.coroutines.launch import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.loading +import mantra.composeapp.generated.resources.no_messages_go_to_a_profile_and_send_them_a +import mantra.composeapp.generated.resources.something_went_wrong class ChatRoomListViewModel( initialChatRoomListUIState: ChatRoomListUIState, @@ -154,7 +159,7 @@ class ChatRoomListViewModel( modifier = Modifier.height(MaterialTheme.spacing.space600) ) Text( - text = "Something went wrong", + text = stringResource(Res.string.something_went_wrong), ) } } @@ -167,7 +172,7 @@ class ChatRoomListViewModel( if (chatRoomListUIState.chatRoomList.isEmpty()) { Text( - text = "No messages. Go to a profile and send them a message." + text = stringResource(Res.string.no_messages_go_to_a_profile_and_send_them_a) ) } else { LazyColumn( @@ -236,7 +241,7 @@ class ChatRoomListViewModel( modifier = Modifier.height(MaterialTheme.spacing.space600) ) Text( - text = "Loading", + text = stringResource(Res.string.loading), textAlign = TextAlign.Center ) Spacer( diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/FeedListViewModel.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/FeedListViewModel.kt index acbc0558..beb7a10b 100755 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/FeedListViewModel.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/FeedListViewModel.kt @@ -35,6 +35,11 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.loading +import mantra.composeapp.generated.resources.no_events_were_found +import mantra.composeapp.generated.resources.something_went_wrong class FeedListViewModel( initialFeedListUIState: FeedListUIState, @@ -121,7 +126,7 @@ class FeedListViewModel( modifier = Modifier.height(MaterialTheme.spacing.space600) ) Text( - text = "Something went wrong", + text = stringResource(Res.string.something_went_wrong), ) } } @@ -135,7 +140,7 @@ class FeedListViewModel( modifier = Modifier.height(MaterialTheme.spacing.space600) ) Text( - text = "No events were found", + text = stringResource(Res.string.no_events_were_found), ) } } else { @@ -172,7 +177,7 @@ class FeedListViewModel( modifier = Modifier.height(MaterialTheme.spacing.space600) ) Text( - text = "Loading", + text = stringResource(Res.string.loading), textAlign = TextAlign.Center ) Spacer( diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/FollowersListViewModel.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/FollowersListViewModel.kt index a4e4c6c6..04e246dd 100755 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/FollowersListViewModel.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/FollowersListViewModel.kt @@ -31,6 +31,11 @@ import kotlinx.coroutines.IO import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.launch import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.loading +import mantra.composeapp.generated.resources.no_events_were_found +import mantra.composeapp.generated.resources.something_went_wrong class FollowersListViewModel( initialFollowingListUIState: press.mantra.compose.ui.view.state.FollowersListUIState, @@ -115,7 +120,7 @@ class FollowersListViewModel( modifier = Modifier.height(MaterialTheme.spacing.space600) ) Text( - text = "Something went wrong", + text = stringResource(Res.string.something_went_wrong), ) } } @@ -129,7 +134,7 @@ class FollowersListViewModel( modifier = Modifier.height(MaterialTheme.spacing.space600) ) Text( - text = "No events were found", + text = stringResource(Res.string.no_events_were_found), ) } } else { @@ -160,7 +165,7 @@ class FollowersListViewModel( modifier = Modifier.height(MaterialTheme.spacing.space600) ) Text( - text = "Loading", + text = stringResource(Res.string.loading), textAlign = TextAlign.Center ) Spacer( diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/FollowingListViewModel.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/FollowingListViewModel.kt index 7c62724b..345ecdef 100755 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/FollowingListViewModel.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/FollowingListViewModel.kt @@ -31,6 +31,11 @@ import kotlinx.coroutines.IO import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.launch import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.loading +import mantra.composeapp.generated.resources.no_events_were_found +import mantra.composeapp.generated.resources.something_went_wrong class FollowingListViewModel( initialFollowingListUIState: press.mantra.compose.ui.view.state.FollowingListUIState, @@ -114,7 +119,7 @@ class FollowingListViewModel( modifier = Modifier.height(MaterialTheme.spacing.space600) ) Text( - text = "Something went wrong", + text = stringResource(Res.string.something_went_wrong), ) } } @@ -128,7 +133,7 @@ class FollowingListViewModel( modifier = Modifier.height(MaterialTheme.spacing.space600) ) Text( - text = "No events were found", + text = stringResource(Res.string.no_events_were_found), ) } } else { @@ -159,7 +164,7 @@ class FollowingListViewModel( modifier = Modifier.height(MaterialTheme.spacing.space600) ) Text( - text = "Loading", + text = stringResource(Res.string.loading), textAlign = TextAlign.Center ) Spacer( diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/InReplyToViewModel.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/InReplyToViewModel.kt index e12bd9f8..a6223751 100755 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/InReplyToViewModel.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/InReplyToViewModel.kt @@ -36,6 +36,11 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.launch import kotlin.time.Instant import press.mantra.compose.ui.theme.spacing +import mantra.composeapp.generated.resources.Res +import org.jetbrains.compose.resources.stringResource +import mantra.composeapp.generated.resources.loading +import mantra.composeapp.generated.resources.no_events_were_found +import mantra.composeapp.generated.resources.something_went_wrong class InReplyToViewModel( val nostrEvent: press.mantra.compose.database.model.NostrEvent, @@ -125,7 +130,7 @@ class InReplyToViewModel( modifier = Modifier.height(MaterialTheme.spacing.space600) ) Text( - text = "Something went wrong", + text = stringResource(Res.string.something_went_wrong), ) } } @@ -139,7 +144,7 @@ class InReplyToViewModel( modifier = Modifier.height(MaterialTheme.spacing.space600) ) Text( - text = "No events were found", + text = stringResource(Res.string.no_events_were_found), ) } } else { @@ -176,7 +181,7 @@ class InReplyToViewModel( modifier = Modifier.height(MaterialTheme.spacing.space600) ) Text( - text = "Loading", + text = stringResource(Res.string.loading), textAlign = TextAlign.Center ) Spacer( diff --git a/composeApp/src/jvmTest/kotlin/press/mantra/compose/ui/StringCatalogueJvmTest.kt b/composeApp/src/jvmTest/kotlin/press/mantra/compose/ui/StringCatalogueJvmTest.kt new file mode 100644 index 00000000..3cfd25e0 --- /dev/null +++ b/composeApp/src/jvmTest/kotlin/press/mantra/compose/ui/StringCatalogueJvmTest.kt @@ -0,0 +1,48 @@ +package press.mantra.compose.ui + +import kotlinx.coroutines.runBlocking +import mantra.composeapp.generated.resources.Res +import mantra.composeapp.generated.resources.currently_no_messages_have_been_shared +import mantra.composeapp.generated.resources.don_t_sign +import mantra.composeapp.generated.resources.something_went_wrong +import org.jetbrains.compose.resources.getString +import kotlin.test.Test +import kotlin.test.assertEquals + +/** + * The string catalogue reads back what the source used to say. + * + * Moving 315 literals out of composables and into `strings.xml` is a rename that a + * compiler cannot check: every call site still compiles if a resource holds the wrong + * text, and the mistake surfaces as wrong words on a screen nobody has opened. + * + * The escapes are the part worth a test rather than an assumption. A string going into an + * XML resource needs `'` escaped as `\'` and `%` doubled, and the generated `.cvr` stores + * the escaped form verbatim -- base64 of `We couldn\'t find...`. Whether the backslash is + * still there when `stringResource` hands the text to a `Text` is a property of the + * resources library, not of the extraction, and the failure mode is an app that literally + * displays `Don\'t sign`. + * + * `getString` is the non-composable reader for the same resources, so this can assert it + * without a composition. + */ +class StringCatalogueJvmTest { + + @Test + fun `an apostrophe survives the round trip through the catalogue`() = runBlocking { + assertEquals("Don't sign", getString(Res.string.don_t_sign)) + } + + @Test + fun `an escaped newline comes back as a newline`() = runBlocking { + assertEquals( + "Currently no messages have been shared.\nBreak the ice.", + getString(Res.string.currently_no_messages_have_been_shared), + ) + } + + @Test + fun `a plain string comes back unchanged`() = runBlocking { + assertEquals("Something went wrong", getString(Res.string.something_went_wrong)) + } +} diff --git a/docs/scripts/m3-extract-strings.py b/docs/scripts/m3-extract-strings.py new file mode 100755 index 00000000..5a399375 --- /dev/null +++ b/docs/scripts/m3-extract-strings.py @@ -0,0 +1,267 @@ +#!/usr/bin/env python3 +"""Move literal UI strings out of composables and into the resource catalogue. + +Handles the simple case only: a `text = "..."` or `Text("...")` whose literal contains no +Kotlin interpolation. Interpolated strings need format placeholders and an argument order +decided per site, which is not something to do blind. + +Resource names are derived from the string's content, snake_cased and truncated at a word +boundary. That is the conventional shape for an automated extraction and it has a known +cost: rewording the copy makes the name a little stale. The alternative -- a name derived +from the string's *purpose* -- needs somebody to read all 285 call sites, and a wrong +purpose in a name is worse than a slightly dated one. + +Usage: + m3-extract-strings.py dry run, prints the plan + m3-extract-strings.py --apply +""" +import os, re, sys, io, collections + +UI = 'composeApp/src/commonMain/kotlin/press/mantra/compose/ui' +STRINGS = 'composeApp/src/commonMain/composeResources/values/strings.xml' +DRY = '--apply' not in sys.argv + +# Literals inside a `Text(...)` call, with no `$` inside. +# +# The first version of this matched a bare `text = "…"` anywhere, which is wrong: `text` +# is an ordinary parameter name and the tree uses it on data classes too. It rewrote +# `NavigationUIState.Loading(text = "…")` -- not a composable -- and the compiler caught +# it with "@Composable invocations can only happen from the context of a @Composable +# function". So the call is brace-matched instead, and only literals genuinely inside a +# `Text(` are touched. +def text_call_spans(source): + """Character ranges of every `Text(` / `BasicText(` call, brace-matched. + + Anchoring to the call is what keeps `NavigationUIState.Loading(text = "…")` out of + the results. `text` is an ordinary parameter name and the tree uses it on data + classes too; an earlier version matched a bare `text = "…"` anywhere and rewrote a + non-composable, which the compiler caught with "@Composable invocations can only + happen from the context of a @Composable function". + """ + spans = [] + for m in re.finditer(r'\b(?:Basic)?Text\s*\(', source): + depth, i = 0, m.end() - 1 + while i < len(source): + if source[i] == '(': + depth += 1 + elif source[i] == ')': + depth -= 1 + if depth == 0: + spans.append((m.start(), i)) + break + i += 1 + return spans + + +def kotlin_strings(source): + """Every top-level Kotlin string literal, as (start, end, body, interpolated). + + A regex cannot do this. `"a ${if (n == 1) "chunk" else "chunks"} b"` contains two + inner literals that belong to the outer template, and matching quote pairs left to + right pulls them out as strings of their own -- which is how an earlier version of + this script decided "chunk" and "note" were UI strings worth translating. + + So the source is scanned: on an opening quote, walk forward tracking `${` depth and + recursing over nested literals, and stop at the closing quote that is at depth zero. + Raw strings and escapes are skipped rather than parsed, which is enough here. + """ + out, i, n = [], 0, len(source) + while i < n: + c = source[i] + if c == '"' and source[i:i + 3] == '\"\"\"': + end = source.find('\"\"\"', i + 3) + i = n if end == -1 else end + 3 + continue + if c != '"': + i += 1 + continue + j, depth, interpolated = i + 1, 0, False + while j < n: + ch = source[j] + if ch == '\\': + j += 2 + continue + if ch == '$' and j + 1 < n and (source[j + 1] == '{' or source[j + 1].isalpha()): + interpolated = True + if source[j + 1] == '{': + depth += 1 + j += 2 + continue + if depth > 0: + if ch == '{': + depth += 1 + elif ch == '}': + depth -= 1 + elif ch == '"': + # a literal inside the interpolation: skip it whole + k = j + 1 + while k < n and source[k] != '"': + k += 2 if source[k] == '\\' else 1 + j = k + j += 1 + continue + if ch == '"': + break + if ch == '\n': + break + j += 1 + if j < n and source[j] == '"': + out.append((i, j + 1, source[i + 1:j], interpolated)) + i = j + 1 + else: + i += 1 + return out + + +def literals_in_text_calls(source): + """(start, end, value) for each plain, whole literal inside a Text( call.""" + spans = text_call_spans(source) + found = [] + for start, end, value, interpolated in kotlin_strings(source): + if interpolated or not value.strip(): + continue + if not any(a <= start <= b for a, b in spans): + continue + line_start = source.rfind('\n', 0, start) + 1 + line = source[line_start:source.find('\n', start)] + if line.lstrip().startswith(('//', '*', '/*')): + continue + # A fragment of a concatenation. `"a " + x + " b"` is one sentence in three + # pieces, and " b" is not a translatable unit -- word order differs between + # languages, so a translator handed " b" has nothing to work with. These go with + # the interpolated strings, which need format placeholders and a human. + before = source[:start].rstrip() + after = source[end:].lstrip() + if before.endswith('+') or after.startswith('+'): + continue + if value != value.strip() or not any(c.isalpha() for c in value): + continue + if before.endswith('append('): + continue + # The same fragment problem one level out. A pluralisation reads + # + # (if (n == 2) "event" else "events") + + # + # so neither literal is adjacent to the `+` -- the parenthesis is. Testing the + # line instead catches those four sites while leaving a genuine either/or alone: + # + # text = if (session == null) "Start key ceremony" else "Try again" + # + # has no `+` on its line and both branches are whole strings. + stripped = line.strip() + if stripped.endswith('+') or stripped.startswith('+'): + continue + found.append((start, end, value)) + return found + + +def resource_name(text, taken): + slug = re.sub(r'[^a-z0-9]+', '_', text.lower()).strip('_') + words = slug.split('_') + name, out = '', [] + for w in words: + if len(name) + len(w) + 1 > 44: + break + out.append(w) + name = '_'.join(out) + name = name or 'string' + if name[0].isdigit(): + name = 's_' + name + base, i = name, 2 + while name in taken: + name = f'{base}_{i}' + i += 1 + return name + + +def xml_escape(text): + """XML entities only. + + Compose Resources is not aapt, and the difference is a shipped bug rather than a + detail. An earlier version of this escaped apostrophes as `\\'` and doubled `%`, which + is what android's resource compiler requires. Compose Resources does neither: + `getString` returned `Don\\'t sign`, backslash included, and + StringCatalogueJvmTest caught it. + + It *does* process `\\n`, which the same test asserts -- so escape handling here is + partial rather than absent, and worth checking per escape rather than assuming a + family. + + `%` is left alone. Nothing in this catalogue contains one, and if something does + later it only matters for an entry passed through `getString(resource, args)`. + """ + return text.replace('&', '&').replace('<', '<').replace('>', '>') + + +def main(): + occurrences = collections.defaultdict(list) + for root, _, files in os.walk(UI): + for f in sorted(files): + if not f.endswith('.kt'): + continue + path = os.path.join(root, f) + src = open(path, encoding='utf-8').read() + for start, _end, value in literals_in_text_calls(src): + occurrences[value].append((path, src[:start].count('\n') + 1)) + + taken, names = set(), {} + for text in sorted(occurrences): + names[text] = resource_name(text, taken) + taken.add(names[text]) + + total = sum(len(v) for v in occurrences.values()) + print(f'{len(occurrences)} distinct strings, {total} occurrences') + if DRY: + for text in sorted(occurrences)[:10]: + print(f' {names[text]:46s} {text[:60]!r}') + print(' ...') + return 0 + + # Rewrite the call sites. + rewritten = 0 + for root, _, files in os.walk(UI): + for f in sorted(files): + if not f.endswith('.kt'): + continue + path = os.path.join(root, f) + src = io.open(path, encoding='utf-8').read() + found = literals_in_text_calls(src) + changed = len(found) + # Right to left, so earlier offsets stay valid. + for start, end, value in reversed(found): + src = src[:start] + f'stringResource(Res.string.{names[value]})' + src[end:] + if changed: + for imp in ('import mantra.composeapp.generated.resources.Res', + 'import org.jetbrains.compose.resources.stringResource'): + if imp not in src: + lines = src.split('\n') + idx = max(i for i, l in enumerate(lines) if l.startswith('import ')) + lines.insert(idx + 1, imp) + src = '\n'.join(lines) + # the generated accessors are one per string, under the same package + need = sorted({names[t] for t in occurrences + if any(p == path for p, _ in occurrences[t])}) + lines = src.split('\n') + idx = max(i for i, l in enumerate(lines) if l.startswith('import ')) + for nm in reversed(need): + imp = f'import mantra.composeapp.generated.resources.{nm}' + if imp not in src: + lines.insert(idx + 1, imp) + src = '\n'.join(lines) + io.open(path, 'w', encoding='utf-8').write(src) + rewritten += changed + print(f'{rewritten} call sites rewritten') + + # Write the catalogue. + existing = io.open(STRINGS, encoding='utf-8').read() + entries = '\n'.join( + f' {xml_escape(t)}' + for t in sorted(occurrences, key=lambda x: names[x])) + io.open(STRINGS, 'w', encoding='utf-8').write( + existing.replace('', entries + '\n')) + print(f'{len(occurrences)} entries written to {STRINGS}') + return 0 + + +if __name__ == '__main__': + sys.exit(main())