Skip to content

Commit 694544f

Browse files
committed
feat: callback interface for translation changes
1 parent 0558232 commit 694544f

6 files changed

Lines changed: 168 additions & 9 deletions

File tree

core/api/android/core.api

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
public class io/tolgee/Tolgee {
22
public static final field Companion Lio/tolgee/Tolgee$Companion;
33
public fun <init> (Lio/tolgee/Tolgee$Config;)V
4+
public final fun addChangeListener (Lio/tolgee/Tolgee$ChangeListener;)V
45
public final fun getChangeFlow ()Lkotlinx/coroutines/flow/MutableSharedFlow;
56
public fun getConfig ()Lio/tolgee/Tolgee$Config;
67
public static final fun getInstance ()Lio/tolgee/TolgeeAndroid;
@@ -12,6 +13,7 @@ public class io/tolgee/Tolgee {
1213
public static final fun new (Lio/tolgee/Tolgee$Config;)Lio/tolgee/TolgeeAndroid;
1314
public static final fun new (Lkotlin/jvm/functions/Function1;)Lio/tolgee/TolgeeAndroid;
1415
public fun preload (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
16+
public final fun removeChangeListener (Lio/tolgee/Tolgee$ChangeListener;)Z
1517
public fun setLocale (Ljava/lang/String;)Ljava/util/Locale;
1618
public fun setLocale (Ljava/util/Locale;)Ljava/util/Locale;
1719
public final fun t (Ljava/lang/String;)Ljava/lang/String;
@@ -24,6 +26,10 @@ public class io/tolgee/Tolgee {
2426
public static synthetic fun tFlow$default (Lio/tolgee/Tolgee;Ljava/lang/String;Lio/tolgee/model/TolgeeMessageParams;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;
2527
}
2628

29+
public abstract interface class io/tolgee/Tolgee$ChangeListener {
30+
public abstract fun onTranslationsChanged ()V
31+
}
32+
2733
public final class io/tolgee/Tolgee$Companion {
2834
public final fun getInstance ()Lio/tolgee/TolgeeAndroid;
2935
public final fun getInstanceOrNull ()Lio/tolgee/TolgeeAndroid;
@@ -167,6 +173,7 @@ public final class io/tolgee/TolgeeAndroid : io/tolgee/Tolgee {
167173
public final fun tPlural (Landroid/content/res/Resources;II[Ljava/lang/Object;)Ljava/lang/String;
168174
public final fun tPluralFlow (Landroid/content/res/Resources;II)Lkotlinx/coroutines/flow/Flow;
169175
public final fun tPluralFlow (Landroid/content/res/Resources;II[Ljava/lang/Object;)Lkotlinx/coroutines/flow/Flow;
176+
public final fun tStyled (Landroid/content/Context;I)Ljava/lang/CharSequence;
170177
public fun toString ()Ljava/lang/String;
171178
}
172179

@@ -200,6 +207,7 @@ public final class io/tolgee/common/ExtendTolgee_androidKt {
200207
public static final fun getStringT (Landroid/content/Context;I[Ljava/lang/Object;)Ljava/lang/String;
201208
public static final fun getStringT (Landroid/content/Context;Lio/tolgee/Tolgee;I)Ljava/lang/String;
202209
public static final fun getStringT (Landroid/content/Context;Lio/tolgee/Tolgee;I[Ljava/lang/Object;)Ljava/lang/String;
210+
public static final fun getTextT (Landroid/content/Context;Lio/tolgee/Tolgee;I)Ljava/lang/CharSequence;
203211
}
204212

205213
public abstract interface class io/tolgee/model/TolgeeMessageParams : de/comahe/i18n4k/messages/formatter/MessageParameters {

core/api/jvm/core.api

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
public class io/tolgee/Tolgee {
22
public static final field Companion Lio/tolgee/Tolgee$Companion;
33
public fun <init> (Lio/tolgee/Tolgee$Config;)V
4+
public final fun addChangeListener (Lio/tolgee/Tolgee$ChangeListener;)V
45
public final fun getChangeFlow ()Lkotlinx/coroutines/flow/MutableSharedFlow;
56
public fun getConfig ()Lio/tolgee/Tolgee$Config;
67
public static final fun getInstance ()Lio/tolgee/common/PlatformTolgee;
@@ -12,6 +13,7 @@ public class io/tolgee/Tolgee {
1213
public static final fun new (Lio/tolgee/Tolgee$Config;)Lio/tolgee/common/PlatformTolgee;
1314
public static final fun new (Lkotlin/jvm/functions/Function1;)Lio/tolgee/common/PlatformTolgee;
1415
public fun preload (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
16+
public final fun removeChangeListener (Lio/tolgee/Tolgee$ChangeListener;)Z
1517
public fun setLocale (Ljava/lang/String;)Ljava/util/Locale;
1618
public fun setLocale (Ljava/util/Locale;)Ljava/util/Locale;
1719
public final fun t (Ljava/lang/String;)Ljava/lang/String;
@@ -24,6 +26,10 @@ public class io/tolgee/Tolgee {
2426
public static synthetic fun tFlow$default (Lio/tolgee/Tolgee;Ljava/lang/String;Lio/tolgee/model/TolgeeMessageParams;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;
2527
}
2628

29+
public abstract interface class io/tolgee/Tolgee$ChangeListener {
30+
public abstract fun onTranslationsChanged ()V
31+
}
32+
2733
public final class io/tolgee/Tolgee$Companion {
2834
public final fun getInstance ()Lio/tolgee/common/PlatformTolgee;
2935
public final fun getInstanceOrNull ()Lio/tolgee/common/PlatformTolgee;

core/src/commonMain/kotlin/io/tolgee/Tolgee.kt

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,52 @@ open class Tolgee(
9898
MutableStateFlow(config.locale)
9999
}
100100

101+
/**
102+
* A flow that emits whenever translations change.
103+
*
104+
* This can be used in to reactively respond to translation changes.
105+
*/
101106
val changeFlow by lazy {
102107
MutableSharedFlow<Unit>()
103108
}
104109

110+
/**
111+
* Interface for listening to changes in Tolgee translations.
112+
*
113+
* This interface provides a callback mechanism for Java code and other environments
114+
* where Kotlin Flows might not be the preferred approach for handling asynchronous events.
115+
*/
116+
interface ChangeListener {
117+
/**
118+
* Called when translations in Tolgee have changed.
119+
*/
120+
fun onTranslationsChanged()
121+
}
122+
123+
/**
124+
* Collection of registered change listeners.
125+
*/
126+
private val changeListeners = mutableSetOf<ChangeListener>()
127+
128+
/**
129+
* Registers a listener to be notified when translations change.
130+
*
131+
* @param listener The listener to register
132+
*/
133+
fun addChangeListener(listener: ChangeListener) {
134+
changeListeners.add(listener)
135+
}
136+
137+
/**
138+
* Unregisters a previously registered change listener.
139+
*
140+
* @param listener The listener to unregister
141+
* @return true if the listener was found and removed, false otherwise
142+
*/
143+
fun removeChangeListener(listener: ChangeListener): Boolean {
144+
return changeListeners.remove(listener)
145+
}
146+
105147

106148
/**
107149
* Loads translations for a given locale or the default locale if none is specified.
@@ -123,6 +165,9 @@ open class Tolgee(
123165
).also {
124166
cachedTranslation.value = it
125167
changeFlow.emit(Unit)
168+
changeListeners.forEach { listener ->
169+
listener.onTranslationsChanged()
170+
}
126171
}
127172
}
128173
}
@@ -226,13 +271,15 @@ open class Tolgee(
226271
*
227272
* @param locale The locale to be set for translations and related operations.
228273
*/
274+
@JvmOverloads
229275
open fun setLocale(locale: Locale) = localeFlow.updateAndGet { locale } ?: locale
230276

231277
/**
232278
* Adjusts the current locale used for translations.
233279
*
234280
* @param localeTag A string representation of the desired locale.
235281
*/
282+
@JvmOverloads
236283
open fun setLocale(localeTag: String) = setLocale(forLocaleTag(localeTag))
237284

238285
/**
Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,25 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
33

4-
<uses-permission android:name="android.permission.INTERNET" />
4+
<uses-permission android:name="android.permission.INTERNET"/>
55

66
<application
77
android:name=".MyApplication"
88
android:allowBackup="true"
99
android:icon="@mipmap/ic_launcher"
1010
android:label="@string/app_name"
11+
android:networkSecurityConfig="@xml/network_security"
1112
android:roundIcon="@mipmap/ic_launcher_round"
12-
android:supportsRtl="true"
13-
android:networkSecurityConfig="@xml/network_security">
13+
android:supportsRtl="true">
14+
<activity
15+
android:name=".MainJavaActivity"
16+
android:exported="true">
17+
<intent-filter>
18+
<action android:name="android.intent.action.MAIN"/>
19+
20+
<category android:name="android.intent.category.LAUNCHER"/>
21+
</intent-filter>
22+
</activity>
1423
<activity
1524
android:name=".MainActivity"
1625
android:exported="true">
@@ -22,4 +31,4 @@
2231
</activity>
2332
</application>
2433

25-
</manifest>
34+
</manifest>

demo/exampleandroid/src/main/java/io/tolgee/demo/exampleandroid/MainActivity.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,15 @@ class MainActivity : ComponentActivity() {
5454

5555
buttonEn.setOnClickListener {
5656
tolgee.setLocale(Locale.ENGLISH)
57-
Tolgee.instance.preload(this)
57+
tolgee.preload(this)
5858
}
5959
buttonFr.setOnClickListener {
6060
tolgee.setLocale(Locale.FRENCH)
61-
Tolgee.instance.preload(this)
61+
tolgee.preload(this)
6262
}
6363
buttonCs.setOnClickListener {
64-
tolgee.setLocale(Locale("cs"))
65-
Tolgee.instance.preload(this)
64+
tolgee.setLocale("cs")
65+
tolgee.preload(this)
6666
}
6767
}
6868

@@ -72,6 +72,6 @@ class MainActivity : ComponentActivity() {
7272
// Make sure the translations are loaded
7373
// This function will initiate translations fetching in the background and
7474
// will trigger changeFlow whenever updated translations are available
75-
Tolgee.instance.preload(this)
75+
tolgee.preload(this)
7676
}
7777
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package io.tolgee.demo.exampleandroid;
2+
3+
import android.content.Context;
4+
import android.os.Bundle;
5+
6+
import android.widget.Button;
7+
import android.widget.TextView;
8+
import androidx.activity.ComponentActivity;
9+
import io.tolgee.TolgeeAndroid;
10+
import io.tolgee.Tolgee;
11+
import io.tolgee.TolgeeContextWrapper;
12+
13+
import java.util.Locale;
14+
15+
public class MainJavaActivity extends ComponentActivity implements Tolgee.ChangeListener {
16+
17+
private final TolgeeAndroid tolgee = Tolgee.getInstance();
18+
19+
@Override
20+
protected void attachBaseContext(Context newBase) {
21+
// Wrapping base context will make sure getString calls will use tolgee
22+
// even for instances which cannot be replaced automatically by the compiler
23+
super.attachBaseContext(TolgeeContextWrapper.wrap(newBase));
24+
}
25+
26+
@Override
27+
protected void onCreate(Bundle savedInstanceState) {
28+
super.onCreate(savedInstanceState);
29+
30+
tolgee.addChangeListener(this);
31+
32+
setContentView(R.layout.activity_main);
33+
34+
// Make sure the app title stays updated
35+
setTitle(R.string.app_name);
36+
37+
TextView name = findViewById(R.id.app_name_text);
38+
TextView basic = findViewById(R.id.basic_text);
39+
TextView parameter = findViewById(R.id.parameterized_text);
40+
TextView plural = findViewById(R.id.plural_text);
41+
TextView array = findViewById(R.id.array_text);
42+
Button buttonEn = findViewById(R.id.button_en);
43+
Button buttonFr = findViewById(R.id.button_fr);
44+
Button buttonCs = findViewById(R.id.button_cs);
45+
46+
// Update texts within the app with translated ones
47+
name.setText(getString(R.string.app_name));
48+
basic.setText(getString(R.string.description));
49+
parameter.setText(getString(R.string.percentage_placeholder, "87"));
50+
plural.setText(getResources().getQuantityString(R.plurals.plr_test_placeholder_2, 2, 3, "Plurals"));
51+
array.setText(String.join(", ", getResources().getStringArray(R.array.array_test)));
52+
53+
buttonEn.setOnClickListener(v -> {
54+
tolgee.setLocale(Locale.ENGLISH);
55+
tolgee.preload(this);
56+
});
57+
buttonFr.setOnClickListener(v -> {
58+
tolgee.setLocale(Locale.FRENCH);
59+
tolgee.preload(this);
60+
});
61+
buttonCs.setOnClickListener(v -> {
62+
tolgee.setLocale("cs");
63+
tolgee.preload(this);
64+
});
65+
}
66+
67+
@Override
68+
protected void onStart() {
69+
super.onStart();
70+
71+
// Make sure the translations are loaded
72+
// This function will initiate translations fetching in the background and
73+
// will trigger changeFlow whenever updated translations are available
74+
tolgee.preload(this);
75+
}
76+
77+
@Override
78+
protected void onDestroy() {
79+
super.onDestroy();
80+
81+
tolgee.removeChangeListener(this);
82+
}
83+
84+
@Override
85+
public void onTranslationsChanged() {
86+
// we want to reload activity after a language change
87+
recreate();
88+
}
89+
}

0 commit comments

Comments
 (0)