feat: Move strings to resources for localization (#2440)

Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net>
Co-authored-by: Aunali321 <aunvakil.aa@gmail.com>

BREAKING CHANGE: Various APIs have been changed.
This commit is contained in:
LisoUseInAIKyrios
2024-01-27 02:34:01 +01:00
committed by GitHub
co-authored by oSumAtrIX semantic-release-bot Aunali321
parent 15a83a6d28
commit 55fb1ebd9d
201 changed files with 3411 additions and 3784 deletions
@@ -0,0 +1,37 @@
package app.revanced.util.resource
import app.revanced.util.childElementsSequence
import org.w3c.dom.Document
import org.w3c.dom.Node
/**
* An array resource.
*
* @param name The name of the array resource.
* @param items The items of the array resource.
*/
@Suppress("MemberVisibilityCanBePrivate")
class ArrayResource(
name: String,
val items: List<String>,
) : BaseResource(name, "string-array") {
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
super.serialize(ownerDocument, resourceCallback).apply {
setAttribute("name", name)
items.forEach { item ->
appendChild(ownerDocument.createElement("item").also { itemNode ->
itemNode.textContent = item
})
}
}
companion object {
fun fromNode(node: Node): ArrayResource {
val key = node.attributes.getNamedItem("name").textContent
val items = node.childElementsSequence().map { it.textContent }.toList()
return ArrayResource(key, items)
}
}
}
@@ -0,0 +1,43 @@
package app.revanced.util.resource
import org.w3c.dom.Document
import org.w3c.dom.Element
/**
* Base resource class for all resources.
*
* @param name The name of the resource.
* @param tag The tag of the resource.
*/
@Suppress("MemberVisibilityCanBePrivate")
abstract class BaseResource(
val name: String,
val tag: String
) {
/**
* Serialize resource element to XML.
* Overriding methods should invoke super and operate on its return value.
* @param ownerDocument Target document to create elements from.
* @param resourceCallback Called when a resource has been processed.
*/
open fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit = { }): Element {
return ownerDocument.createElement(tag).apply {
setAttribute("name", name)
}
}
override fun hashCode(): Int {
var result = name.hashCode()
result = 31 * result + tag.hashCode()
return result
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as BaseResource
return name == other.name
}
}
@@ -0,0 +1,41 @@
package app.revanced.util.resource
import app.revanced.patcher.patch.PatchException
import org.w3c.dom.Document
import org.w3c.dom.Node
/**
* A string value.
* Represents a string in the strings.xml file.
*
* @param name The name of the string.
* @param value The value of the string.
* @param formatted If the string is formatted. Defaults to `true`.
*/
class StringResource(
name: String,
val value: String,
val formatted: Boolean = true,
) : BaseResource(name, "string") {
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
super.serialize(ownerDocument, resourceCallback).apply {
// if the string is un-formatted, explicitly add the formatted attribute
if (!formatted) setAttribute("formatted", "false")
if (value.contains(Regex("(?<!\\\\)['\"]")))
throw PatchException("String $name cannot contain unescaped quotes in value \"$value\".")
textContent = value
}
companion object {
fun fromNode(node: Node): StringResource {
val name = node.attributes.getNamedItem("name").textContent
val value = node.textContent
// TODO: Should this be true by default? It is too in the constructor of StringResource.
val formatted = node.attributes.getNamedItem("formatted")?.textContent?.toBoolean() ?: true
return StringResource(name, value, formatted)
}
}
}