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())