diff --git a/project/MornyConfiguration.scala b/project/MornyConfiguration.scala
index dee41cb..d08d67a 100644
--- a/project/MornyConfiguration.scala
+++ b/project/MornyConfiguration.scala
@@ -8,7 +8,7 @@ object MornyConfiguration {
val MORNY_CODE_STORE = "https://github.com/Eyre-S/Coeur-Morny-Cono"
val MORNY_COMMIT_PATH = "https://github.com/Eyre-S/Coeur-Morny-Cono/commit/%s"
- val VERSION = "2.0.0-alpha18"
+ val VERSION = "2.0.0-alpha19"
val VERSION_DELTA: Option[String] = None
val CODENAME = "xinzheng"
diff --git a/src/main/resources/assets_morny/langs/en_us.hyt b/src/main/resources/assets_morny/langs/en_us.hyt
index 3382989..a0d7e75 100644
--- a/src/main/resources/assets_morny/langs/en_us.hyt
+++ b/src/main/resources/assets_morny/langs/en_us.hyt
@@ -4,11 +4,26 @@
&encoding=utf8
&indent=1
+morny.information.about_links
+| source code | backup
+| Feedback / issue tracker
+| User's Guide / documentations
+
morny.command.info.message.about
| Morny Cono
| An assistant rat(micromys minutus) from Annie。
| ————————————————
-| {about_links}
+| {morny.information.about_links}
+
+morny.command.info.sub_start.message
+| Welcome you meet the Morny Cono,an assistant rat from Annie。
+| Morny has a lot variety of features。
+|
+| ————————————————
+| {morny.information.about_links}
+| ————————————————
+|
+| (You can use /info command to get these message in any time)
morny.command.info.version
| version:
@@ -50,4 +65,4 @@ morny.command.info.message.tasks
morny.command.info.message.event
| Event Statistics :
| in today
-| {event_statistics}""".stripMargin
+| {event_statistics}
diff --git a/src/main/resources/assets_morny/langs/zh_cn.hyt b/src/main/resources/assets_morny/langs/zh_cn.hyt
index 6a08f79..a546422 100644
--- a/src/main/resources/assets_morny/langs/zh_cn.hyt
+++ b/src/main/resources/assets_morny/langs/zh_cn.hyt
@@ -4,8 +4,40 @@
&encoding=utf8
&indent=1
-morny.command.info.about
+morny.information.about_links
+| source code | backup
+| 反馈 / issue tracker
+| 使用说明书 / user guide & docs
+
+morny.command.info.message.about
| Morny Cono
| 来自安妮的侍从小鼠。
| ————————————————
-| {about_links}
+| {morny.information.about_links}
+
+morny.command.info.sub_start.message
+| 欢迎使用 Morny Cono,来自安妮的侍从小鼠。
+| Morny 具有各种各样的功能。
+|
+| ————————————————
+| {morny.information.about_links}
+| ————————————————
+|
+| (你可以随时通过 /info 重新获得这些信息)
+
+morny.misc.command_test.message
+| 这只是一个 /test 测试命令。测试 id 为 1
。
+| 你可以回复一条消息来测试回复消息的功能。
+
+morny.misc.command_test.branch_normal.message
+| 你完成了一个回复消息的测试!
+| 你所回复的消息为:
+|
+| {replied_message}
+
+morny.misc.command_test.branch_oops.err_message_simple
+| 将会生成一条错误! (使用 /inspect 命令来洞察错误详细信息)
+
+morny.misc.command_test.branch_oops.err_message_complex
+| Oops: There is just a test error.
+| 这个错误是由 /test 命令手动触发的,为了测试错误洞察命令是否可以正常工作。
diff --git a/src/main/resources/assets_morny/langs/zh_tw.hyt b/src/main/resources/assets_morny/langs/zh_tw.hyt
new file mode 100644
index 0000000..4437d8e
--- /dev/null
+++ b/src/main/resources/assets_morny/langs/zh_tw.hyt
@@ -0,0 +1,16 @@
+ Morny Translations File
+
+%1.0
+&encoding=utf8
+&indent=1
+
+morny.information.about_links
+| source code | backup
+| 回饋 / issue tracker
+| 使用說明書 / user guide & docs
+
+morny.command.info.message.about
+| Morny Cono
+| 來自安妮的侍從小鼠。
+| ————————————————
+| {morny.information.about_links}
diff --git a/src/main/scala/cc/sukazyo/cono/morny/core/MornyCoeur.scala b/src/main/scala/cc/sukazyo/cono/morny/core/MornyCoeur.scala
index a0deba0..f0655ed 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/core/MornyCoeur.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/core/MornyCoeur.scala
@@ -2,7 +2,7 @@ package cc.sukazyo.cono.morny.core
import cc.sukazyo.cono.morny.core.Log.logger
import cc.sukazyo.cono.morny.core.MornyCoeur.*
-import cc.sukazyo.cono.morny.core.bot.api.{EventListenerManager, MornyCommandManager, MornyQueryManager}
+import cc.sukazyo.cono.morny.core.bot.api.{BotExtension, EventListenerManager, MornyCommandManager, MornyQueryManager}
import cc.sukazyo.cono.morny.core.bot.api.messages.ThreadingManager
import cc.sukazyo.cono.morny.core.bot.event.{MornyOnInlineQuery, MornyOnTelegramCommand, MornyOnUpdateTimestampOffsetLock}
import cc.sukazyo.cono.morny.core.bot.internal.{ErrorMessageManager, ThreadingManagerImpl}
@@ -15,6 +15,7 @@ import cc.sukazyo.cono.morny.util.time.WatchDog
import cc.sukazyo.cono.morny.util.GivenContext
import cc.sukazyo.cono.morny.util.UseString.MString
import cc.sukazyo.cono.morny.util.UseThrowable.toLogString
+import cc.sukazyo.cono.morny.util.hytrans.Translations
import com.pengrad.telegrambot.TelegramBot
import com.pengrad.telegrambot.request.GetMe
@@ -127,6 +128,12 @@ class MornyCoeur (modules: List[MornyModule])(using val config: MornyConfig)(tes
)}
|"""
+ ///>>> BLOCK START local storage / data configuration
+
+ val lang: MornyLangs = MornyLangs()
+
+ ///>>> BLOCK END local storage / data configuration
+
///>>> BLOCK START instance configure & startup stage 1
logger `info` "Coeur starting..."
@@ -324,6 +331,47 @@ class MornyCoeur (modules: List[MornyModule])(using val config: MornyConfig)(tes
///<<< BLOCK END instance configure & startup stage 2
+ /** Provide DSLs of Morny Coeur
+ *
+ * Provide the following coeur values to using/given context:
+ *
+ * - Coeur itself
+ * - its Telegram bot account: [[MornyCoeur.account]]
+ * - its i18n translation instance: [[MornyCoeur.lang.translations]]
+ *
+ * Also provides the DSLs defined in [[BotExtension]].
+ *
+ * You can simply add the following line to use the vals and DSL functions in your code:
+ *
+ * {{{
+ * // assuming the Coeur instance is coeur
+ * import coeur.dsl.given
+ *
+ * // now you can use the vals in your code
+ * translations.trans(/* ... */)
+ * // or use as an implicit/using value
+ * import com.pengrad.telegrambot.request.SendMessage
+ * import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Requests.unsafeExecute
+ * SendMessage(/* ... */)
+ * .unsafeExecute // implicitly use coeur.account
+ *
+ * // you need to use the * import to use DSL functions
+ * import coeur.dsl.*
+ * // or use the following line to import both vals and DSL functions
+ * import coeur.dsl.{*, given}
+ *
+ * // now you can use the DSL functions in your code
+ * import com.pengrad.telegrambot.model.User
+ * val prefer_languge = user.asInstanceOf[User].prefer_language
+ *
+ * }}}
+ */
+ object dsl extends BotExtension {
+ given coeur: MornyCoeur = MornyCoeur.this
+ given account: TelegramBot = MornyCoeur.this.account
+ given translations: Translations = MornyCoeur.this.lang.translations
+ }
+
def saveDataAll(): Unit = {
modules.foreach(it => it.onRoutineSavingData)
logger `notice` "done all save action."
@@ -396,7 +444,8 @@ class MornyCoeur (modules: List[MornyModule])(using val config: MornyConfig)(tes
logger `info` s"Succeed logged in to @${remote.username}"
break(Some(LoginResult(account, remote.username, remote.id)))
} catch
- case r: boundary.Break[Option[LoginResult]] => throw r
+ /* boundary.Break[Option[LoginResult] */
+ case r: boundary.Break[_] => throw r
case e: Throwable =>
logger `error`
s"""${e.toLogString}
diff --git a/src/main/scala/cc/sukazyo/cono/morny/core/MornyLangs.scala b/src/main/scala/cc/sukazyo/cono/morny/core/MornyLangs.scala
new file mode 100644
index 0000000..2a86535
--- /dev/null
+++ b/src/main/scala/cc/sukazyo/cono/morny/core/MornyLangs.scala
@@ -0,0 +1,68 @@
+package cc.sukazyo.cono.morny.core
+
+import cc.sukazyo.cono.morny.core.Log.logger
+import cc.sukazyo.cono.morny.data.MornyAssets
+import cc.sukazyo.cono.morny.util.hytrans.*
+import cc.sukazyo.cono.morny.util.UseThrowable.toLogString
+
+import java.io.IOException
+import scala.collection.mutable
+import scala.util.boundary
+import scala.util.boundary.break
+
+class MornyLangs {
+
+ private val (lang_index, lang_trans) = {
+
+ logger `info` s"Loading Morny's translation data."
+
+ val (lang_dir, lang_index_content) = try {(
+ MornyAssets.pack.getResDir("langs"),
+ MornyAssets.pack.getResource("langs/_index.hyl").readAsString()
+ )} catch case e: IOException =>
+ throw Exception("Cannot read Morny's translations file.", e)
+ val my_index = LanguageTree.parseTreeDocument(lang_index_content)
+ val indexed_langs: Set[String] = {
+ val lang_tags = mutable.ListBuffer.empty[String]
+ my_index.root.traverseTree(lang_tags += _.langTag.lang)
+ logger `info` s"indexed following languages: ${lang_tags.mkString(", ")}"
+ lang_tags.toSet
+ }
+
+ val language_translations = mutable.HashMap.empty[String, Definitions]
+
+ for (file <- lang_dir.listFiles().filter(_.isFile)) yield { boundary {
+ import file.getPath as raw_path
+ if !(raw_path.endsWith(".hyt") || raw_path.endsWith(".hytrans")) then break()
+ val file_name = file.getPath.reverse.takeWhile(c=>(c!='/')&&(c !='\\')).reverse
+ val file_basename = file_name.dropRight(
+ if file_name.endsWith(".hyt") then ".hyt".length
+ else ".hytrans".length
+ )
+ val normalized = LangTag.normalizeLangTag(file_basename)
+ if !indexed_langs.contains(normalized) then
+ logger `warn` s"translation file \"$file_name\" is not in language index, so it got ignored (normalized lang name is \"$normalized\")."
+ break()
+ val lang_def = try {
+ val content = file.readAsString()
+ Parser.parse(content)
+ } catch case e: IOException =>
+ logger `error`
+ s"""Failed read/parse translation file $file_name (normalized lang name is $normalized):
+ |${e.toLogString.indent(2)}
+ |due to failed, this ($file_name) has been ignored.""".stripMargin
+ break()
+ logger `info` s"read language file $file_name (normalized lang name is $normalized), with ${lang_def.size} entries."
+ if language_translations contains normalized then
+ // TODO: merge
+ logger `warn` s" language $normalized seems already loaded one yet, this will override the old one!"
+ else language_translations += (normalized -> lang_def)
+ }}
+
+ (my_index, language_translations.toMap)
+
+ }
+
+ val translations: Translations = Translations(lang_index, lang_trans)
+
+}
diff --git a/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/BotExtension.scala b/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/BotExtension.scala
index 6647406..edec824 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/BotExtension.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/BotExtension.scala
@@ -2,10 +2,13 @@ package cc.sukazyo.cono.morny.core.bot.api
import cc.sukazyo.cono.morny.core.MornyCoeur
import cc.sukazyo.cono.morny.core.bot.api.messages.ErrorMessage
+import cc.sukazyo.cono.morny.util.hytrans.LangTag
+import com.pengrad.telegrambot.model.User
-/** Bot extensions for Morny feature.
- */
-object BotExtension {
+object BotExtension extends BotExtension
+
+/** Bot extensions for Morny feature. */
+trait BotExtension {
extension (errorMessage: ErrorMessage[?, ?]) {
@@ -21,4 +24,13 @@ object BotExtension {
}
+ extension (user: User) {
+
+ def prefer_language: String =
+ user.languageCode match
+ case null => ""
+ case x => LangTag.normalizeLangTag(x)
+
+ }
+
}
diff --git a/src/main/scala/cc/sukazyo/cono/morny/core/bot/command/MornyInfoOnStart.scala b/src/main/scala/cc/sukazyo/cono/morny/core/bot/command/MornyInfoOnStart.scala
index b9c2dfa..6d9c449 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/core/bot/command/MornyInfoOnStart.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/core/bot/command/MornyInfoOnStart.scala
@@ -2,35 +2,30 @@ package cc.sukazyo.cono.morny.core.bot.command
import cc.sukazyo.cono.morny.core.MornyCoeur
import cc.sukazyo.cono.morny.core.bot.api.{ICommandAlias, ISimpleCommand}
-import cc.sukazyo.cono.morny.data.MornyInformation.{getAboutPic, getMornyAboutLinksHTML}
+import cc.sukazyo.cono.morny.data.MornyInformation.{getAboutPic, getMornyAboutLinksVars}
import cc.sukazyo.cono.morny.util.tgapi.InputCommand
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Requests.unsafeExecute
import com.pengrad.telegrambot.model.Update
import com.pengrad.telegrambot.model.request.ParseMode
import com.pengrad.telegrambot.request.SendPhoto
-import com.pengrad.telegrambot.TelegramBot
class MornyInfoOnStart (using coeur: MornyCoeur) extends ISimpleCommand {
- private given TelegramBot = coeur.account
+ import coeur.dsl.{*, given}
override val name: String = "start"
override val aliases: List[ICommandAlias] = Nil
override def execute (using command: InputCommand, event: Update): Unit = {
+ given lang: String = event.message.from.prefer_language
SendPhoto(
event.message.chat.id,
getAboutPic
).caption(
- s"""欢迎使用 Morny Cono,来自安妮的侍从小鼠。
- |Morny 具有各种各样的功能。
- |
- |————————————————
- |$getMornyAboutLinksHTML
- |————————————————
- |
- |(你可以随时通过 /info 重新获得这些信息)"""
- .stripMargin
+ translations.trans(
+ "morny.command.info.sub_start.message",
+ translations.transAsVar("morny.information.about_links", getMornyAboutLinksVars*)
+ ).stripMargin
).parseMode(ParseMode HTML)
.unsafeExecute
diff --git a/src/main/scala/cc/sukazyo/cono/morny/core/bot/command/MornyInformation.scala b/src/main/scala/cc/sukazyo/cono/morny/core/bot/command/MornyInformation.scala
index 33a54aa..fc5091d 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/core/bot/command/MornyInformation.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/core/bot/command/MornyInformation.scala
@@ -3,7 +3,6 @@ package cc.sukazyo.cono.morny.core.bot.command
import cc.sukazyo.cono.morny.core.{MornyCoeur, MornySystem}
import cc.sukazyo.cono.morny.core.bot.api.{ICommandAlias, ITelegramCommand}
import cc.sukazyo.cono.morny.core.bot.api.messages.{ErrorMessage, MessagingContext}
-import cc.sukazyo.cono.morny.core.Log.logger
import cc.sukazyo.cono.morny.data.MornyInformation.*
import cc.sukazyo.cono.morny.data.TelegramStickers
import cc.sukazyo.cono.morny.reporter.MornyReport
@@ -16,11 +15,11 @@ import cc.sukazyo.cono.morny.util.var_text.VarText
import com.pengrad.telegrambot.model.Update
import com.pengrad.telegrambot.model.request.ParseMode
import com.pengrad.telegrambot.request.{SendMessage, SendPhoto, SendSticker}
-import com.pengrad.telegrambot.TelegramBot
import java.lang.System
+
class MornyInformation (using coeur: MornyCoeur) extends ITelegramCommand {
- private given TelegramBot = coeur.account
+ import coeur.dsl.{*, given}
private case object Subs {
val STICKERS = "stickers"
@@ -76,19 +75,10 @@ class MornyInformation (using coeur: MornyCoeur) extends ITelegramCommand {
cxt.bind_chat.id,
getAboutPic
).caption(
- // language=html
- (VarText(
- """Morny Cono
- |来自安妮的侍从小鼠。
- |————————————————
- |{about_links}""".stripMargin
- ).render(
- "about_links" -> getMornyAboutLinksHTML
- ) :: Nil)
- .map( f =>
- logger `trace` f
- f
- ).head
+ translations.trans(
+ "morny.command.info.message.about",
+ translations.transAsVar("morny.information.about_links", getMornyAboutLinksVars*)(using cxt.bind_message.from.prefer_language)
+ )(using cxt.bind_message.from.prefer_language)
).parseMode(ParseMode HTML).replyToMessageId(cxt.bind_message.messageId)
.unsafeExecute
@@ -229,7 +219,7 @@ class MornyInformation (using coeur: MornyCoeur) extends ITelegramCommand {
)
).parseMode(ParseMode.HTML).replyToMessageId(update.message.messageId)
.unsafeExecute
- }
+ }
private def echoEventStatistics (using update: Update): Unit = {
coeur.externalContext >> { (reporter: MornyReport) =>
diff --git a/src/main/scala/cc/sukazyo/cono/morny/data/MornyInformation.scala b/src/main/scala/cc/sukazyo/cono/morny/data/MornyInformation.scala
index 9718003..571559a 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/data/MornyInformation.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/data/MornyInformation.scala
@@ -1,7 +1,7 @@
package cc.sukazyo.cono.morny.data
import cc.sukazyo.cono.morny.core.{MornyAbout, MornySystem}
-import cc.sukazyo.cono.morny.util.var_text.VarText
+import cc.sukazyo.cono.morny.util.var_text.Var
import java.net.InetAddress
import java.rmi.UnknownHostException
@@ -39,13 +39,8 @@ object MornyInformation {
def getAboutPic: Array[Byte] = TelegramImages.IMG_ABOUT get
- def getMornyAboutLinksHTML: String =
- VarText(
- // language=html
- """source code | backup
- |反馈 / issue tracker
- |使用说明书 / user guide & docs""".stripMargin
- ).render(
+ def getMornyAboutLinksVars: List[Var] =
+ List(
"MORNY_SOURCECODE_LINK" -> MornyAbout.MORNY_SOURCECODE_LINK,
"MORNY_SOURCECODE_SELF_HOSTED_MIRROR_LINK" -> MornyAbout.MORNY_SOURCECODE_SELF_HOSTED_MIRROR_LINK,
"MORNY_ISSUE_TRACKER_LINK" -> MornyAbout.MORNY_ISSUE_TRACKER_LINK,
diff --git a/src/main/scala/cc/sukazyo/cono/morny/morny_misc/Testing.scala b/src/main/scala/cc/sukazyo/cono/morny/morny_misc/Testing.scala
index 92919ce..6744ca6 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/morny_misc/Testing.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/morny_misc/Testing.scala
@@ -3,29 +3,26 @@ package cc.sukazyo.cono.morny.morny_misc
import cc.sukazyo.cono.morny.core.MornyCoeur
import cc.sukazyo.cono.morny.core.bot.api.{ICommandAlias, ISimpleCommand}
import cc.sukazyo.cono.morny.core.bot.api.messages.{ErrorMessage, MessagingContext}
-import cc.sukazyo.cono.morny.core.bot.api.BotExtension.submit
import cc.sukazyo.cono.morny.data.TelegramStickers
import cc.sukazyo.cono.morny.util.tgapi.InputCommand
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Requests.unsafeExecute
import com.pengrad.telegrambot.model.{Message, Update}
import com.pengrad.telegrambot.model.request.ParseMode
import com.pengrad.telegrambot.request.{SendMessage, SendSticker}
-import com.pengrad.telegrambot.TelegramBot
class Testing (using coeur: MornyCoeur) extends ISimpleCommand {
- private given TelegramBot = coeur.account
+ import coeur.dsl.{*, given}
override val name: String = "test"
override val aliases: List[ICommandAlias] = Nil
override def execute (using command: InputCommand, event: Update): Unit = {
given context: MessagingContext.WithUserAndMessage = MessagingContext.extract(using event.message)
+ given lang: String = context.bind_user.prefer_language
SendMessage(
event.message.chat.id,
- // language=html
- "Just a TEST command.\n"
- + "Please input something to test the command."
+ translations.trans("morny.misc.command_test.message")
).replyToMessageId(event.message.messageId).parseMode(ParseMode HTML)
.unsafeExecute
@@ -34,11 +31,13 @@ class Testing (using coeur: MornyCoeur) extends ISimpleCommand {
}
private def execute2 (message: Message, previousContext: MessagingContext.WithUserAndMessage): Unit = {
+ given context: MessagingContext.WithUserAndMessage = MessagingContext.extract(using message)
+ given lang: String = context.bind_user.prefer_language
if (message.text == "oops")
SendMessage(
message.chat.id,
- "A test error message will be generated."
+ translations.trans("morny.misc.command_test.branch_oops.err_message_simple")
).replyToMessageId(message.messageId)
.unsafeExecute
ErrorMessage(
@@ -48,16 +47,17 @@ class Testing (using coeur: MornyCoeur) extends ISimpleCommand {
).replyToMessageId(message.messageId),
_complex = SendMessage(
message.chat.id,
- "Oops: There is just a test error."
+ translations.trans("morny.misc.command_test.branch_oops.err_message_complex")
).replyToMessageId(message.messageId)
- )(using MessagingContext.extract(using message))
- .submit
+ ).submit
return;
SendMessage(
message.chat.id,
- // language=html
- "Test command with following input:\n" + message.text
+ translations.trans(
+ "morny.misc.command_test.branch_normal.message",
+ "replied_message" -> message.text
+ )
).replyToMessageId(message.messageId).parseMode(ParseMode HTML)
.unsafeExecute
diff --git a/src/main/scala/cc/sukazyo/cono/morny/util/hytrans/Parser.scala b/src/main/scala/cc/sukazyo/cono/morny/util/hytrans/Parser.scala
index ec29786..941d463 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/util/hytrans/Parser.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/util/hytrans/Parser.scala
@@ -24,6 +24,7 @@ object Parser {
case Some(' ') | Some('\t') | None => // empty lines, will be ignored
case Some('#') => // comment line, will be ignored
case Some('%') => // document meta definition line, currently not supported
+ case Some('&') => // document meta definition line, currently not supported
case Some('|') => // content line
addLine(line drop 2)
case Some(_) => // a key definition line
diff --git a/src/main/scala/cc/sukazyo/cono/morny/util/hytrans/Translations.scala b/src/main/scala/cc/sukazyo/cono/morny/util/hytrans/Translations.scala
index 906fcef..6ebd177 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/util/hytrans/Translations.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/util/hytrans/Translations.scala
@@ -1,6 +1,7 @@
package cc.sukazyo.cono.morny.util.hytrans
import cc.sukazyo.cono.morny.util.var_text.{Var, VarText}
+import cc.sukazyo.cono.morny.util.var_text.Var.String_As_VarText
import scala.util.boundary
@@ -42,4 +43,7 @@ class Translations (
def trans (key: String, args: Var*)(using lang: String): String =
trans(key).render(args*)
+ def transAsVar (key: String, args: Var*)(using lang: String): Var =
+ trans(key, args*).asVar(key)
+
}
diff --git a/src/main/scala/cc/sukazyo/cono/morny/util/var_text/Var.scala b/src/main/scala/cc/sukazyo/cono/morny/util/var_text/Var.scala
index 9e88f89..5fd4e40 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/util/var_text/Var.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/util/var_text/Var.scala
@@ -8,7 +8,7 @@ import scala.language.implicitConversions
*
* You can just call the [[Var]] constructor to create a new Var, or use the implicit
* conversion to create a var from a tuple of ([[String]], [[String]]), or use the extension
- * method [[Var.StringAsVarText.asVar]] to convert a [[String]] to a var.
+ * method [[Var.String_As_VarText.asVar]] to convert a [[String]] to a var.
*
* @since 2.0.0
*
@@ -77,11 +77,11 @@ object Var {
*
* @since 2.0.0
*/
- implicit def StrStrTupleAsVar (tuple: (String, Any)): Var =
+ implicit def StrStrTuple_as_Var (tuple: (String, Any)): Var =
Var(tuple._1, tuple._2.toString)
/** @see [[asVar]] */
- implicit class StringAsVarText (text: String):
+ implicit class String_As_VarText (text: String):
/** Convert this string text to a [[Var]].
* @since 2.0.0
* @param id the var-id.
diff --git a/src/main/scala/cc/sukazyo/cono/morny/util/var_text/VarText.scala b/src/main/scala/cc/sukazyo/cono/morny/util/var_text/VarText.scala
index c0ac344..f29b855 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/util/var_text/VarText.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/util/var_text/VarText.scala
@@ -2,6 +2,8 @@ package cc.sukazyo.cono.morny.util.var_text
import cc.sukazyo.cono.morny.util.var_text.Var.isLegalId
+import scala.language.implicitConversions
+
/** A text/string template that may contains some named replaceable variables. It's concept may
* be similar with scala's `StringContext` or `GString` in groovy.
*
@@ -56,6 +58,9 @@ object VarText {
def apply (_nodes: VTNode*): VarText = new VarText:
override val nodes: List[VTNode] = _nodes.toList
+ implicit def VarText_is_String (varText: VarText): String =
+ varText.render()
+
private val symbol_escape = '/'
private val symbol_var_start = '{'
private val symbol_var_end = '}'