Skip to content

Commit 6fdfb55

Browse files
authored
Merge pull request #1350 from OneSignal/feat/set_language_for_3.X.X
Feature App-defined Language implementation backported to 3.X.X version
2 parents 3515ae9 + 678ff8b commit 6fdfb55

12 files changed

+220
-35
lines changed

OneSignalSDK/onesignal/src/main/java/com/onesignal/NotificationChannelManager.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
import android.support.annotation.RequiresApi;
4040
import android.support.v4.app.NotificationManagerCompat;
4141

42+
import com.onesignal.language.LanguageContext;
43+
4244
import org.json.JSONArray;
4345
import org.json.JSONException;
4446
import org.json.JSONObject;
@@ -113,9 +115,9 @@ private static String createChannel(Context context, NotificationManager notific
113115
JSONObject payloadWithText = channelPayload;
114116
if (channelPayload.has("langs")) {
115117
JSONObject langList = channelPayload.getJSONObject("langs");
116-
String deviceLanguage = OSUtils.getCorrectedLanguage();
117-
if (langList.has(deviceLanguage))
118-
payloadWithText = langList.optJSONObject(deviceLanguage);
118+
String language = LanguageContext.getInstance().getLanguage();
119+
if (langList.has(language))
120+
payloadWithText = langList.optJSONObject(language);
119121
}
120122

121123
String channel_name = payloadWithText.optString("nm", "Miscellaneous");

OneSignalSDK/onesignal/src/main/java/com/onesignal/OSInAppMessageController.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import com.onesignal.OSDynamicTriggerController.OSDynamicTriggerControllerObserver;
1111
import com.onesignal.OneSignalRestClient.ResponseHandler;
12+
import com.onesignal.language.LanguageContext;
1213

1314
import org.json.JSONArray;
1415
import org.json.JSONException;
@@ -34,6 +35,7 @@ class OSInAppMessageController implements OSDynamicTriggerControllerObserver, OS
3435
public static final String IN_APP_MESSAGES_JSON_KEY = "in_app_messages";
3536
private static final String OS_SAVE_IN_APP_MESSAGE = "OS_SAVE_IN_APP_MESSAGE";
3637
private static final Object LOCK = new Object();
38+
private final LanguageContext languageContext;
3739

3840
OSTriggerController triggerController;
3941
private OSSystemConditionController systemConditionController;
@@ -70,14 +72,15 @@ class OSInAppMessageController implements OSDynamicTriggerControllerObserver, OS
7072
Date lastTimeInAppDismissed = null;
7173
private int htmlNetworkRequestAttemptCount = 0;
7274

73-
protected OSInAppMessageController(OneSignalDbHelper dbHelper) {
75+
protected OSInAppMessageController(OneSignalDbHelper dbHelper, LanguageContext languageContext) {
7476
messages = new ArrayList<>();
7577
dismissedMessages = OSUtils.newConcurrentSet();
7678
messageDisplayQueue = new ArrayList<>();
7779
impressionedMessages = OSUtils.newConcurrentSet();
7880
clickedClickIds = OSUtils.newConcurrentSet();
7981
triggerController = new OSTriggerController(this);
8082
systemConditionController = new OSSystemConditionController(this);
83+
this.languageContext = languageContext;
8184

8285
Set<String> tempDismissedSet = OneSignalPrefs.getStringSet(
8386
OneSignalPrefs.PREFS_ONESIGNAL,
@@ -209,16 +212,16 @@ private void evaluateInAppMessages() {
209212
}
210213
}
211214

212-
private static @Nullable String variantIdForMessage(@NonNull OSInAppMessage message) {
213-
String languageIdentifier = OSUtils.getCorrectedLanguage();
215+
private @Nullable String variantIdForMessage(@NonNull OSInAppMessage message) {
216+
String language = languageContext.getLanguage();
214217

215218
for (String variant : PREFERRED_VARIANT_ORDER) {
216219
if (!message.variants.containsKey(variant))
217220
continue;
218221

219222
HashMap<String, String> variantMap = message.variants.get(variant);
220-
if (variantMap.containsKey(languageIdentifier))
221-
return variantMap.get(languageIdentifier);
223+
if (variantMap.containsKey(language))
224+
return variantMap.get(language);
222225
return variantMap.get("default");
223226
}
224227

@@ -655,7 +658,7 @@ public void run() {
655658
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "persistInAppMessageForRedisplay: " + message.toString() + " with msg array data: " + redisplayedInAppMessages.toString());
656659
}
657660

658-
private static @Nullable
661+
private @Nullable
659662
String htmlPathForMessage(OSInAppMessage message) {
660663
String variantId = variantIdForMessage(message);
661664

OneSignalSDK/onesignal/src/main/java/com/onesignal/OSInAppMessageControllerFactory.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,23 @@
2929

3030
import android.os.Build;
3131

32+
import com.onesignal.language.LanguageContext;
33+
3234
class OSInAppMessageControllerFactory {
3335

3436
private static final Object LOCK = new Object();
3537

3638
private OSInAppMessageController controller;
3739

38-
public OSInAppMessageController getController(OneSignalDbHelper dbHelper) {
40+
public OSInAppMessageController getController(OneSignalDbHelper dbHelper, LanguageContext languageContext) {
3941
if (controller == null) {
4042
synchronized (LOCK) {
4143
if (controller == null) {
4244
// Make sure only Android 4.4 devices and higher can use IAMs
4345
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR2)
44-
controller = new OSInAppMessageDummyController(null);
46+
controller = new OSInAppMessageDummyController(null, languageContext);
4547
else
46-
controller = new OSInAppMessageController(dbHelper);
48+
controller = new OSInAppMessageController(dbHelper, languageContext);
4749
}
4850
}
4951
}

OneSignalSDK/onesignal/src/main/java/com/onesignal/OSInAppMessageDummyController.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import android.support.annotation.NonNull;
44
import android.support.annotation.Nullable;
55

6+
import com.onesignal.language.LanguageContext;
7+
68
import org.json.JSONArray;
79
import org.json.JSONException;
810
import org.json.JSONObject;
@@ -17,8 +19,8 @@ class OSInAppMessageDummyController extends OSInAppMessageController {
1719
* This is a dummy controller that will be used for Android 4.3 and older devices
1820
* All methods should be overridden and as empty as possible (few return exceptions)
1921
*/
20-
OSInAppMessageDummyController(OneSignalDbHelper dbHelper) {
21-
super(dbHelper);
22+
OSInAppMessageDummyController(OneSignalDbHelper dbHelper, LanguageContext languageContext) {
23+
super(dbHelper, languageContext);
2224
}
2325

2426
@Override

OneSignalSDK/onesignal/src/main/java/com/onesignal/OSUtils.java

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@
6060
import java.util.Collections;
6161
import java.util.HashSet;
6262
import java.util.Iterator;
63-
import java.util.Locale;
6463
import java.util.Set;
6564
import java.util.UUID;
6665
import java.util.concurrent.ConcurrentHashMap;
@@ -437,24 +436,6 @@ static String getResourceString(Context context, String key, String defaultStr)
437436
return defaultStr;
438437
}
439438

440-
static String getCorrectedLanguage() {
441-
String lang = Locale.getDefault().getLanguage();
442-
443-
// https://github.com/OneSignal/OneSignal-Android-SDK/issues/64
444-
if (lang.equals("iw"))
445-
return "he";
446-
if (lang.equals("in"))
447-
return "id";
448-
if (lang.equals("ji"))
449-
return "yi";
450-
451-
// https://github.com/OneSignal/OneSignal-Android-SDK/issues/98
452-
if (lang.equals("zh"))
453-
return lang + "-" + Locale.getDefault().getCountry();
454-
455-
return lang;
456-
}
457-
458439
static boolean isValidEmail(String email) {
459440
if (email == null)
460441
return false;

OneSignalSDK/onesignal/src/main/java/com/onesignal/OneSignal.java

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@
4949
import com.onesignal.influence.OSTrackerFactory;
5050
import com.onesignal.influence.model.OSInfluence;
5151
import com.onesignal.outcomes.OSOutcomeEventsFactory;
52+
import com.onesignal.language.LanguageContext;
53+
import com.onesignal.language.LanguageProviderAppDefined;
54+
import com.onesignal.language.LanguageProviderDevice;
5255

5356
import org.json.JSONArray;
5457
import org.json.JSONException;
@@ -416,6 +419,8 @@ static Activity getCurrentActivity() {
416419
private static String userId = null, emailId = null;
417420
private static int subscribableStatus;
418421

422+
private static LanguageContext languageContext = null;
423+
419424
// Is the init() of OneSignal SDK finished yet
420425
private static boolean initDone;
421426
static boolean isInitDone() {
@@ -460,7 +465,7 @@ public void onSessionEnding(@NonNull List<OSInfluence> lastInfluences) {
460465

461466
private static OSInAppMessageControllerFactory inAppMessageControllerFactory = new OSInAppMessageControllerFactory();
462467
static OSInAppMessageController getInAppMessageController() {
463-
return inAppMessageControllerFactory.getController(getDBHelperInstance());
468+
return inAppMessageControllerFactory.getController(getDBHelperInstance(), languageContext);
464469
}
465470
private static OSLogger logger = new OSLogWrapper();
466471
private static OneSignalAPIClient apiClient = new OneSignalRestClientWrapper();
@@ -647,6 +652,9 @@ public static void setAppContext(@NonNull Context context) {
647652
ActivityLifecycleListener.registerActivityLifecycleCallbacks((Application)appContext);
648653

649654
if (wasAppContextNull) {
655+
// Initialize languageContext
656+
languageContext = new LanguageContext(preferences);
657+
650658
if (outcomeEventsFactory == null)
651659
outcomeEventsFactory = new OSOutcomeEventsFactory(logger, apiClient, getDBHelperInstance(), preferences);
652660

@@ -1394,7 +1402,7 @@ private static void registerUserTask() throws JSONException {
13941402
}
13951403
deviceInfo.put("device_os", Build.VERSION.RELEASE);
13961404
deviceInfo.put("timezone", getTimeZoneOffset());
1397-
deviceInfo.put("language", OSUtils.getCorrectedLanguage());
1405+
deviceInfo.put("language", languageContext.getLanguage());
13981406
deviceInfo.put("sdk", VERSION);
13991407
deviceInfo.put("sdk_type", sdkType);
14001408
deviceInfo.put("android_package", packageName);
@@ -1569,6 +1577,36 @@ public void run() {
15691577
emailLogout.run();
15701578
}
15711579

1580+
public static void setLanguage(@NonNull final String language) {
1581+
Runnable runSetLanguage = new Runnable() {
1582+
@Override
1583+
public void run() {
1584+
LanguageProviderAppDefined languageProviderAppDefined = new LanguageProviderAppDefined(preferences);
1585+
languageProviderAppDefined.setLanguage(language);
1586+
languageContext.setStrategy(languageProviderAppDefined);
1587+
1588+
try {
1589+
JSONObject deviceInfo = new JSONObject();
1590+
deviceInfo.put("language", languageContext.getLanguage());
1591+
OneSignalStateSynchronizer.updateDeviceInfo(deviceInfo);
1592+
} catch (JSONException exception) {
1593+
exception.printStackTrace();
1594+
}
1595+
}
1596+
};
1597+
1598+
// If either the app context is null or the waiting queue isn't done (to preserve operation order)
1599+
if (appContext == null || shouldRunTaskThroughQueue()) {
1600+
addTaskToQueue(new PendingTaskRunnable(runSetLanguage));
1601+
return;
1602+
}
1603+
1604+
if (shouldLogUserPrivacyConsentErrorMessageForMethodName("setLanguage()"))
1605+
return;
1606+
1607+
runSetLanguage.run();
1608+
}
1609+
15721610
public static void setExternalUserId(@NonNull final String externalId) {
15731611
setExternalUserId(externalId, null, null);
15741612
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.onesignal.language;
2+
3+
import android.support.annotation.NonNull;
4+
import android.util.Log;
5+
6+
import com.onesignal.OSSharedPreferences;
7+
8+
import static com.onesignal.language.LanguageProviderAppDefined.PREFS_OS_LANGUAGE;
9+
10+
/*
11+
The Interface implements a getter and setter for the Language Provider.
12+
It defaults to the device defined Language unless a language override is set.
13+
*/
14+
public class LanguageContext {
15+
private LanguageProvider strategy;
16+
private static LanguageContext instance = null;
17+
18+
public static LanguageContext getInstance() {
19+
return instance;
20+
}
21+
22+
public LanguageContext(OSSharedPreferences preferences) {
23+
instance = this;
24+
String languageAppDefined = preferences.getString(preferences.getPreferencesName(), PREFS_OS_LANGUAGE, null);
25+
if (languageAppDefined != null) {
26+
this.strategy = new LanguageProviderAppDefined(preferences);
27+
}
28+
else {
29+
this.strategy = new LanguageProviderDevice();
30+
}
31+
}
32+
33+
public void setStrategy(LanguageProvider strategy) {
34+
this.strategy = strategy;
35+
}
36+
37+
@NonNull
38+
public String getLanguage() {
39+
return strategy.getLanguage();
40+
}
41+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.onesignal.language;
2+
3+
import android.support.annotation.NonNull;
4+
5+
public interface LanguageProvider {
6+
@NonNull
7+
String getLanguage();
8+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.onesignal.language;
2+
import android.support.annotation.NonNull;
3+
4+
import com.onesignal.OSSharedPreferences;
5+
6+
public class LanguageProviderAppDefined implements LanguageProvider {
7+
public static final String PREFS_OS_LANGUAGE = "PREFS_OS_LANGUAGE";
8+
9+
private static final String DEFAULT_LANGUAGE = "en";
10+
private final OSSharedPreferences preferences;
11+
12+
public LanguageProviderAppDefined(OSSharedPreferences preferences) {
13+
this.preferences = preferences;
14+
}
15+
16+
public void setLanguage(String language) {
17+
preferences.saveString(
18+
preferences.getPreferencesName(),
19+
PREFS_OS_LANGUAGE,
20+
language);
21+
}
22+
23+
@NonNull
24+
public String getLanguage() {
25+
return preferences.getString(
26+
preferences.getPreferencesName(), PREFS_OS_LANGUAGE, DEFAULT_LANGUAGE);
27+
}
28+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.onesignal.language;
2+
3+
import android.support.annotation.NonNull;
4+
5+
import java.util.Locale;
6+
7+
public class LanguageProviderDevice implements LanguageProvider {
8+
private static final String HEBREW_INCORRECT = "iw";
9+
private static final String HEBREW_CORRECTED = "he";
10+
private static final String INDONESIAN_INCORRECT = "in";
11+
private static final String INDONESIAN_CORRECTED = "id";
12+
private static final String YIDDISH_INCORRECT = "ji";
13+
private static final String YIDDISH_CORRECTED = "yi";
14+
private static final String CHINESE = "zh";
15+
16+
@NonNull
17+
public String getLanguage() {
18+
String language = Locale.getDefault().getLanguage();
19+
20+
switch (language) {
21+
// https://github.com/OneSignal/OneSignal-Android-SDK/issues/64
22+
case HEBREW_INCORRECT:
23+
return HEBREW_CORRECTED;
24+
case INDONESIAN_INCORRECT:
25+
return INDONESIAN_CORRECTED;
26+
case YIDDISH_INCORRECT:
27+
return YIDDISH_CORRECTED;
28+
// https://github.com/OneSignal/OneSignal-Android-SDK/issues/98
29+
case CHINESE:
30+
return language + "-" + Locale.getDefault().getCountry();
31+
default:
32+
return language;
33+
}
34+
}
35+
}

0 commit comments

Comments
 (0)