Skip to content

Commit 8551365

Browse files
committed
fix #7
1 parent 2090fa9 commit 8551365

File tree

4 files changed

+286
-30
lines changed

4 files changed

+286
-30
lines changed

core/src/androidMain/kotlin/io/tolgee/TolgeeAndroid.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,18 @@ data class TolgeeAndroid internal constructor(
159159
} ?: context.getText(id)
160160
}
161161

162+
fun tPluralStyled(resources: Resources, @PluralsRes id: Int, quantity: Int): CharSequence {
163+
return getKeyFromResources(resources, id)?.let { key ->
164+
t(key, TolgeeMessageParams.Indexed(quantity))
165+
} ?: resources.getQuantityText(id, quantity)
166+
}
167+
168+
fun tArrayStyled(resources: Resources, @ArrayRes id: Int): Array<out CharSequence> {
169+
return getKeyFromResources(resources, id)?.let { key ->
170+
tArray(key).toTypedArray()
171+
} ?: resources.getTextArray(id)
172+
}
173+
162174
/**
163175
* Preloads the required languages and their translations for the current Tolgee instance.
164176
*

core/src/androidMain/kotlin/io/tolgee/TolgeeContextWrapper.kt

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,8 @@ class TolgeeContextWrapper(
1919
val tolgee: Tolgee
2020
) : ContextWrapper(base) {
2121

22-
private val res = atomic<Resources?>(null)
23-
2422
override fun getResources(): Resources? {
25-
if (res.value == null) {
26-
val superResources: Resources? = super.getResources()
27-
28-
if (superResources != null) {
29-
res.compareAndSet(null, TolgeeResources(
30-
baseContext = base,
31-
base = superResources,
32-
tolgee = tolgee
33-
))
34-
}
35-
36-
}
37-
return res.value ?: super.getResources()
23+
return TolgeeResources(base, tolgee)
3824
}
3925

4026
companion object {
Lines changed: 259 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,49 @@
11
package io.tolgee
22

3+
import android.annotation.SuppressLint
34
import android.content.Context
5+
import android.content.res.AssetFileDescriptor
6+
import android.content.res.ColorStateList
7+
import android.content.res.Configuration
48
import android.content.res.Resources
9+
import android.content.res.TypedArray
10+
import android.content.res.XmlResourceParser
11+
import android.content.res.loader.ResourcesLoader
12+
import android.graphics.Movie
13+
import android.graphics.Typeface
14+
import android.graphics.drawable.Drawable
15+
import android.os.Build
16+
import android.os.Bundle
17+
import android.util.AttributeSet
18+
import android.util.DisplayMetrics
19+
import android.util.TypedValue
20+
import androidx.annotation.AnimRes
21+
import androidx.annotation.AnimatorRes
22+
import androidx.annotation.AnyRes
23+
import androidx.annotation.ArrayRes
24+
import androidx.annotation.BoolRes
25+
import androidx.annotation.ColorInt
26+
import androidx.annotation.ColorRes
27+
import androidx.annotation.DimenRes
28+
import androidx.annotation.Discouraged
29+
import androidx.annotation.DrawableRes
30+
import androidx.annotation.FontRes
31+
import androidx.annotation.FractionRes
32+
import androidx.annotation.IntegerRes
33+
import androidx.annotation.LayoutRes
34+
import androidx.annotation.PluralsRes
35+
import androidx.annotation.RawRes
36+
import androidx.annotation.RequiresApi
37+
import androidx.annotation.StringRes
38+
import androidx.annotation.StyleableRes
39+
import androidx.annotation.XmlRes
540
import io.tolgee.common.getQuantityStringT
41+
import io.tolgee.common.getQuantityTextT
642
import io.tolgee.common.getStringArrayT
743
import io.tolgee.common.getStringT
44+
import io.tolgee.common.getTextArrayT
845
import io.tolgee.common.getTextT
46+
import java.io.InputStream
947

1048
/**
1149
* Ignore Deprecation: Resources constructor is not really deprecated, apps should just not create
@@ -14,32 +52,238 @@ import io.tolgee.common.getTextT
1452
*/
1553
@Suppress("DEPRECATION")
1654
internal class TolgeeResources(
17-
val baseContext: Context,
18-
val base: Resources,
55+
val base: Context,
1956
val tolgee: Tolgee
20-
) : Resources(base.assets, base.displayMetrics, base.configuration) {
57+
) : Resources(base.resources.assets, base.resources.displayMetrics, base.resources.configuration) {
2158

22-
override fun getString(id: Int): String {
23-
return baseContext.getStringT(tolgee, id)
59+
/**
60+
* Following methods are intercepted by Tolgee.
61+
*/
62+
63+
override fun getString(@StringRes id: Int): String {
64+
return base.getStringT(tolgee, id)
65+
}
66+
67+
override fun getString(@StringRes id: Int, vararg formatArgs: Any?): String {
68+
return base.getStringT(tolgee, id, *formatArgs.filterNotNull().toTypedArray())
69+
}
70+
71+
override fun getQuantityString(@PluralsRes id: Int, quantity: Int): String {
72+
return base.resources.getQuantityStringT(tolgee, id, quantity)
73+
}
74+
75+
override fun getQuantityString(@PluralsRes id: Int, quantity: Int, vararg formatArgs: Any?): String {
76+
return base.resources.getQuantityStringT(tolgee, id, quantity, *formatArgs.filterNotNull().toTypedArray())
77+
}
78+
79+
override fun getStringArray(@ArrayRes id: Int): Array<out String?> {
80+
return base.resources.getStringArrayT(tolgee, id)
81+
}
82+
83+
override fun getText(@StringRes id: Int): CharSequence {
84+
return base.getTextT(tolgee, id)
85+
}
86+
87+
override fun getQuantityText(@PluralsRes id: Int, quantity: Int): CharSequence {
88+
return base.resources.getQuantityTextT(tolgee, id, quantity)
89+
}
90+
91+
override fun getTextArray(id: Int): Array<out CharSequence?> {
92+
return base.resources.getTextArrayT(tolgee, id)
93+
}
94+
95+
/**
96+
* Following methods are proxied to preserve original behavior.
97+
*/
98+
99+
@RequiresApi(Build.VERSION_CODES.O)
100+
override fun getFont(@FontRes id: Int): Typeface {
101+
return base.resources.getFont(id)
102+
}
103+
104+
override fun getIntArray(@ArrayRes id: Int): IntArray {
105+
return base.resources.getIntArray(id)
106+
}
107+
108+
override fun obtainTypedArray(@ArrayRes id: Int): TypedArray {
109+
return base.resources.obtainTypedArray(id)
110+
}
111+
112+
override fun getDimension(@DimenRes id: Int): Float {
113+
return base.resources.getDimension(id)
114+
}
115+
116+
override fun getDimensionPixelOffset(@DimenRes id: Int): Int {
117+
return base.resources.getDimensionPixelOffset(id)
118+
}
119+
120+
override fun getDimensionPixelSize(@DimenRes id: Int): Int {
121+
return base.resources.getDimensionPixelSize(id)
122+
}
123+
124+
override fun getFraction(@FractionRes id: Int, base: Int, pbase: Int): Float {
125+
return this.base.resources.getFraction(id, base, pbase)
126+
}
127+
128+
@Deprecated("Proxied Deprecation")
129+
override fun getDrawable(@DrawableRes id: Int): Drawable? {
130+
return base.resources.getDrawable(id)
131+
}
132+
133+
override fun getDrawable(@DrawableRes id: Int, theme: Theme?): Drawable? {
134+
return base.resources.getDrawable(id, theme)
135+
}
136+
137+
@Deprecated("Proxied Deprecation")
138+
override fun getDrawableForDensity(@DrawableRes id: Int, density: Int): Drawable? {
139+
return base.resources.getDrawableForDensity(id, density)
140+
}
141+
142+
override fun getDrawableForDensity(@DrawableRes id: Int, density: Int, theme: Theme?): Drawable? {
143+
return base.resources.getDrawableForDensity(id, density, theme)
144+
}
145+
146+
@Deprecated("Proxied Deprecation")
147+
override fun getMovie(@RawRes id: Int): Movie? {
148+
return base.resources.getMovie(id)
149+
}
150+
151+
@ColorInt
152+
@Deprecated("Proxied Deprecation")
153+
override fun getColor(@ColorRes id: Int): Int {
154+
return base.resources.getColor(id)
155+
}
156+
157+
@ColorInt
158+
@RequiresApi(Build.VERSION_CODES.M)
159+
override fun getColor(@ColorRes id: Int, theme: Theme?): Int {
160+
return base.resources.getColor(id, theme)
161+
}
162+
163+
@Deprecated("Proxied Deprecation")
164+
override fun getColorStateList(@ColorRes id: Int): ColorStateList {
165+
return base.resources.getColorStateList(id)
166+
}
167+
168+
@RequiresApi(Build.VERSION_CODES.M)
169+
override fun getColorStateList(@ColorRes id: Int, theme: Theme?): ColorStateList {
170+
return base.resources.getColorStateList(id, theme)
171+
}
172+
173+
override fun getBoolean(@BoolRes id: Int): Boolean {
174+
return base.resources.getBoolean(id)
175+
}
176+
177+
override fun getInteger(@IntegerRes id: Int): Int {
178+
return base.resources.getInteger(id)
179+
}
180+
181+
@RequiresApi(Build.VERSION_CODES.Q)
182+
override fun getFloat(@DimenRes id: Int): Float {
183+
return base.resources.getFloat(id)
184+
}
185+
186+
override fun getLayout(@LayoutRes id: Int): XmlResourceParser {
187+
return base.resources.getLayout(id)
188+
}
189+
190+
override fun getAnimation(@AnimatorRes @AnimRes id: Int): XmlResourceParser {
191+
return base.resources.getAnimation(id)
192+
}
193+
194+
override fun getXml(@XmlRes id: Int): XmlResourceParser {
195+
return base.resources.getXml(id)
196+
}
197+
198+
override fun openRawResource(@RawRes id: Int): InputStream {
199+
return base.resources.openRawResource(id)
200+
}
201+
202+
override fun openRawResource(@RawRes id: Int, value: TypedValue?): InputStream {
203+
return base.resources.openRawResource(id, value)
204+
}
205+
206+
override fun openRawResourceFd(@RawRes id: Int): AssetFileDescriptor? {
207+
return base.resources.openRawResourceFd(id)
208+
}
209+
210+
override fun getValue(@AnyRes id: Int, outValue: TypedValue?, resolveRefs: Boolean) {
211+
return base.resources.getValue(id, outValue, resolveRefs)
212+
}
213+
214+
override fun getValueForDensity(
215+
@AnyRes id: Int,
216+
density: Int,
217+
outValue: TypedValue?,
218+
resolveRefs: Boolean
219+
) {
220+
return base.resources.getValueForDensity(id, density, outValue, resolveRefs)
221+
}
222+
223+
@SuppressLint("DiscouragedApi")
224+
@Discouraged("Proxied Discourage")
225+
override fun getValue(name: String?, outValue: TypedValue?, resolveRefs: Boolean) {
226+
return base.resources.getValue(name, outValue, resolveRefs)
227+
}
228+
229+
override fun obtainAttributes(set: AttributeSet?, @StyleableRes attrs: IntArray?): TypedArray? {
230+
return base.resources.obtainAttributes(set, attrs)
231+
}
232+
233+
@Deprecated("Proxied Deprecation")
234+
override fun updateConfiguration(config: Configuration?, metrics: DisplayMetrics?) {
235+
return base.resources.updateConfiguration(config, metrics)
236+
}
237+
238+
override fun getDisplayMetrics(): DisplayMetrics? {
239+
return base.resources.displayMetrics
240+
}
241+
242+
override fun getConfiguration(): Configuration? {
243+
return base.resources.configuration
244+
}
245+
246+
@SuppressLint("DiscouragedApi")
247+
@Discouraged("Proxied Discourage")
248+
override fun getIdentifier(name: String?, defType: String?, defPackage: String?): Int {
249+
return base.resources.getIdentifier(name, defType, defPackage)
250+
}
251+
252+
override fun getResourceName(@AnyRes resid: Int): String? {
253+
return base.resources.getResourceName(resid)
254+
}
255+
256+
override fun getResourcePackageName(@AnyRes resid: Int): String? {
257+
return base.resources.getResourcePackageName(resid)
258+
}
259+
260+
override fun getResourceEntryName(@AnyRes resid: Int): String? {
261+
return base.resources.getResourceEntryName(resid)
262+
}
263+
264+
override fun parseBundleExtras(parser: XmlResourceParser?, outBundle: Bundle?) {
265+
return base.resources.parseBundleExtras(parser, outBundle)
24266
}
25267

26-
override fun getString(id: Int, vararg formatArgs: Any?): String {
27-
return baseContext.getStringT(tolgee, id, *formatArgs.filterNotNull().toTypedArray())
268+
override fun parseBundleExtra(tagName: String?, attrs: AttributeSet?, outBundle: Bundle?) {
269+
return base.resources.parseBundleExtra(tagName, attrs, outBundle)
28270
}
29271

30-
override fun getQuantityString(id: Int, quantity: Int): String {
31-
return baseContext.resources.getQuantityStringT(tolgee, id, quantity)
272+
@RequiresApi(Build.VERSION_CODES.R)
273+
override fun addLoaders(vararg loaders: ResourcesLoader?) {
274+
return base.resources.addLoaders(*loaders)
32275
}
33276

34-
override fun getQuantityString(id: Int, quantity: Int, vararg formatArgs: Any?): String {
35-
return baseContext.resources.getQuantityStringT(tolgee, id, quantity, *formatArgs.filterNotNull().toTypedArray())
277+
@RequiresApi(Build.VERSION_CODES.R)
278+
override fun removeLoaders(vararg loaders: ResourcesLoader?) {
279+
return base.resources.removeLoaders(*loaders)
36280
}
37281

38-
override fun getStringArray(id: Int): Array<out String?> {
39-
return baseContext.resources.getStringArrayT(tolgee, id)
282+
override fun getResourceTypeName(@AnyRes resid: Int): String? {
283+
return base.resources.getResourceTypeName(resid)
40284
}
41285

42-
override fun getText(id: Int): CharSequence {
43-
return baseContext.getTextT(tolgee, id)
286+
override fun getText(@StringRes id: Int, def: CharSequence?): CharSequence? {
287+
return base.resources.getText(id, def)
44288
}
45289
}

core/src/androidMain/kotlin/io/tolgee/common/ExtendTolgee.android.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,20 @@ fun Context.getTextT(tolgee: Tolgee, @StringRes resId: Int): CharSequence {
169169
} ?: this.getText(resId)
170170
}
171171

172+
fun Resources.getQuantityTextT(tolgee: Tolgee, @PluralsRes resId: Int, quantity: Int): CharSequence {
173+
return (tolgee as? TolgeeAndroid)?.tPluralStyled(this, resId, quantity)
174+
?: TolgeeAndroid.getKeyFromResources(this, resId)?.let {
175+
tolgee.t(key = it, parameters = TolgeeMessageParams.Indexed(quantity))
176+
} ?: this.getQuantityText(resId, quantity)
177+
}
178+
179+
fun Resources.getTextArrayT(tolgee: Tolgee, @ArrayRes resId: Int): Array<out CharSequence> {
180+
return (tolgee as? TolgeeAndroid)?.tArrayStyled(this, resId)
181+
?: TolgeeAndroid.getKeyFromResources(this, resId)?.let {
182+
tolgee.tArray(key = it).toTypedArray()
183+
} ?: this.getTextArray(resId)
184+
}
185+
172186
internal actual val platformStorage: TolgeeStorageProvider?
173187
get() = null
174188

0 commit comments

Comments
 (0)