1111import android .os .Build ;
1212import android .text .TextUtils ;
1313import android .text .format .DateUtils ;
14+ import android .text .BidiFormatter ;
1415import android .util .DisplayMetrics ;
1516import android .util .Log ;
1617
4546import java .util .Objects ;
4647import java .util .stream .Collectors ;
4748
48-
4949/*
5050 * Created by chschtsch on 12/29/15.
5151 *
@@ -71,17 +71,21 @@ public final class Localization {
7171 public static final String DOT_SEPARATOR = " • " ;
7272 private static PrettyTime prettyTime ;
7373
74- private Localization () { }
74+ private Localization () {
75+ }
7576
7677 @ NonNull
7778 public static String concatenateStrings (final String ... strings ) {
7879 return concatenateStrings (DOT_SEPARATOR , Arrays .asList (strings ));
7980 }
8081
82+ // Use of BidiFormater to fix text direction automatically
8183 @ NonNull
8284 public static String concatenateStrings (final String delimiter , final List <String > strings ) {
85+ final BidiFormatter bidi = BidiFormatter .getInstance ();
8386 return strings .stream ()
8487 .filter (string -> !TextUtils .isEmpty (string ))
88+ .map ((s ) -> strings .indexOf (s ) == 0 ? bidi .unicodeWrap (s ) : s ) // only wrap username
8589 .collect (Collectors .joining (delimiter ));
8690 }
8791
@@ -123,15 +127,15 @@ public static String localizeNumber(@NonNull final Context context, final double
123127 }
124128
125129 public static String formatDate (@ NonNull final Context context ,
126- @ NonNull final OffsetDateTime offsetDateTime ) {
130+ @ NonNull final OffsetDateTime offsetDateTime ) {
127131 return DateTimeFormatter .ofLocalizedDate (FormatStyle .MEDIUM )
128132 .withLocale (getAppLocale (context )).format (offsetDateTime
129133 .atZoneSameInstant (ZoneId .systemDefault ()));
130134 }
131135
132136 @ SuppressLint ("StringFormatInvalid" )
133137 public static String localizeUploadDate (@ NonNull final Context context ,
134- @ NonNull final OffsetDateTime offsetDateTime ) {
138+ @ NonNull final OffsetDateTime offsetDateTime ) {
135139 return context .getString (R .string .upload_date_text , formatDate (context , offsetDateTime ));
136140 }
137141
@@ -141,7 +145,7 @@ public static String localizeViewCount(@NonNull final Context context, final lon
141145 }
142146
143147 public static String localizeStreamCount (@ NonNull final Context context ,
144- final long streamCount ) {
148+ final long streamCount ) {
145149 switch ((int ) streamCount ) {
146150 case (int ) ListExtractor .ITEM_COUNT_UNKNOWN :
147151 return "" ;
@@ -156,7 +160,7 @@ public static String localizeStreamCount(@NonNull final Context context,
156160 }
157161
158162 public static String localizeStreamCountMini (@ NonNull final Context context ,
159- final long streamCount ) {
163+ final long streamCount ) {
160164 switch ((int ) streamCount ) {
161165 case (int ) ListExtractor .ITEM_COUNT_UNKNOWN :
162166 return "" ;
@@ -170,7 +174,7 @@ public static String localizeStreamCountMini(@NonNull final Context context,
170174 }
171175
172176 public static String localizeWatchingCount (@ NonNull final Context context ,
173- final long watchingCount ) {
177+ final long watchingCount ) {
174178 return getQuantity (context , R .plurals .watching , R .string .no_one_watching , watchingCount ,
175179 localizeNumber (context , watchingCount ));
176180 }
@@ -202,7 +206,7 @@ public static String listeningCount(@NonNull final Context context, final long l
202206 }
203207
204208 public static String shortWatchingCount (@ NonNull final Context context ,
205- final long watchingCount ) {
209+ final long watchingCount ) {
206210 return getQuantity (context , R .plurals .watching , R .string .no_one_watching , watchingCount ,
207211 shortCount (context , watchingCount ));
208212 }
@@ -213,7 +217,7 @@ public static String shortViewCount(@NonNull final Context context, final long v
213217 }
214218
215219 public static String shortSubscriberCount (@ NonNull final Context context ,
216- final long subscriberCount ) {
220+ final long subscriberCount ) {
217221 return getQuantity (context , R .plurals .subscribers , R .string .no_subscribers , subscriberCount ,
218222 shortCount (context , subscriberCount ));
219223 }
@@ -224,7 +228,7 @@ public static String downloadCount(@NonNull final Context context, final int dow
224228 }
225229
226230 public static String deletedDownloadCount (@ NonNull final Context context ,
227- final int deletedCount ) {
231+ final int deletedCount ) {
228232 return getQuantity (context , R .plurals .deleted_downloads_toast , 0 ,
229233 deletedCount , shortCount (context , deletedCount ));
230234 }
@@ -235,10 +239,12 @@ public static String replyCount(@NonNull final Context context, final int replyC
235239 }
236240
237241 /**
238- * @param context the Android context
242+ * @param context the Android context
239243 * @param likeCount the like count, possibly negative if unknown
240- * @return if {@code likeCount} is smaller than {@code 0}, the string {@code "-"}, otherwise
241- * the result of calling {@link #shortCount(Context, long)} on the like count
244+ * @return if {@code likeCount} is smaller than {@code 0}, the string
245+ * {@code "-"}, otherwise
246+ * the result of calling {@link #shortCount(Context, long)} on the like
247+ * count
242248 */
243249 public static String likeCount (@ NonNull final Context context , final int likeCount ) {
244250 if (likeCount < 0 ) {
@@ -249,7 +255,8 @@ public static String likeCount(@NonNull final Context context, final int likeCou
249255 }
250256
251257 /**
252- * Get a readable text for a duration in the format {@code hours:minutes:seconds}.
258+ * Get a readable text for a duration in the format
259+ * {@code hours:minutes:seconds}.
253260 *
254261 * @param duration the duration in seconds
255262 * @return a formatted duration String or {@code 00:00} if the duration is zero.
@@ -259,16 +266,18 @@ public static String getDurationString(final long duration) {
259266 }
260267
261268 /**
262- * Get a readable text for a duration in the format {@code hours:minutes:seconds+}. If the given
269+ * Get a readable text for a duration in the format
270+ * {@code hours:minutes:seconds+}. If the given
263271 * duration is incomplete, a plus is appended to the duration string.
264272 *
265- * @param duration the duration in seconds
266- * @param isDurationComplete whether the given duration is complete or whether info is missing
273+ * @param duration the duration in seconds
274+ * @param isDurationComplete whether the given duration is complete or whether
275+ * info is missing
267276 * @param showDurationPrefix whether the duration-prefix shall be shown
268277 * @return a formatted duration String or {@code 00:00} if the duration is zero.
269278 */
270279 public static String getDurationString (final long duration , final boolean isDurationComplete ,
271- final boolean showDurationPrefix ) {
280+ final boolean showDurationPrefix ) {
272281 final String output = getDurationString (duration );
273282 final String durationPrefix = showDurationPrefix ? "⏱ " : "" ;
274283 final String durationPostfix = isDurationComplete ? "" : "+" ;
@@ -278,16 +287,19 @@ public static String getDurationString(final long duration, final boolean isDura
278287 /**
279288 * Localize an amount of seconds into a human readable string.
280289 *
281- * <p>The seconds will be converted to the closest whole time unit.
282- * <p>For example, 60 seconds would give "1 minute", 119 would also give "1 minute".
290+ * <p>
291+ * The seconds will be converted to the closest whole time unit.
292+ * <p>
293+ * For example, 60 seconds would give "1 minute", 119 would also give "1
294+ * minute".
283295 *
284296 * @param context used to get plurals resources.
285297 * @param durationInSecs an amount of seconds.
286298 * @return duration in a human readable string.
287299 */
288300 @ NonNull
289301 public static String localizeDuration (@ NonNull final Context context ,
290- final int durationInSecs ) {
302+ final int durationInSecs ) {
291303 if (durationInSecs < 0 ) {
292304 throw new IllegalArgumentException ("duration can not be negative" );
293305 }
@@ -313,11 +325,13 @@ public static String localizeDuration(@NonNull final Context context,
313325 /**
314326 * Get the localized name of an audio track.
315327 *
316- * <p>Examples of results returned by this method:</p>
328+ * <p>
329+ * Examples of results returned by this method:
330+ * </p>
317331 * <ul>
318- * <li>English (original)</li>
319- * <li>English (descriptive)</li>
320- * <li>Spanish (Spain) (dubbed)</li>
332+ * <li>English (original)</li>
333+ * <li>English (descriptive)</li>
334+ * <li>Spanish (Spain) (dubbed)</li>
321335 * </ul>
322336 *
323337 * @param context the context used to get the app language
@@ -343,7 +357,7 @@ public static String audioTrackName(@NonNull final Context context, final AudioS
343357
344358 @ NonNull
345359 private static String audioTrackType (@ NonNull final Context context ,
346- @ NonNull final AudioTrackType trackType ) {
360+ @ NonNull final AudioTrackType trackType ) {
347361 return switch (trackType ) {
348362 case ORIGINAL -> context .getString (R .string .audio_track_type_original );
349363 case DUBBED -> context .getString (R .string .audio_track_type_dubbed );
@@ -352,9 +366,11 @@ private static String audioTrackType(@NonNull final Context context,
352366 };
353367 }
354368
355- /*//////////////////////////////////////////////////////////////////////////
356- // Pretty Time
357- //////////////////////////////////////////////////////////////////////////*/
369+ /*
370+ * //////////////////////////////////////////////////////////////////////////
371+ * // Pretty Time
372+ * //////////////////////////////////////////////////////////////////////////
373+ */
358374
359375 public static void initPrettyTime (@ NonNull final PrettyTime time ) {
360376 prettyTime = time ;
@@ -371,19 +387,26 @@ public static String relativeTime(@NonNull final OffsetDateTime offsetDateTime)
371387 }
372388
373389 /**
374- * @param context the Android context; if {@code null} then even if in debug mode and the
375- * setting is enabled, {@code textual} will not be shown next to {@code parsed}
376- * @param parsed the textual date or time ago parsed by NewPipeExtractor, or {@code null} if
390+ * @param context the Android context; if {@code null} then even if in debug
391+ * mode and the
392+ * setting is enabled, {@code textual} will not be shown next to
393+ * {@code parsed}
394+ * @param parsed the textual date or time ago parsed by NewPipeExtractor, or
395+ * {@code null} if
377396 * the extractor could not parse it
378- * @param textual the original textual date or time ago string as provided by services
379- * @return {@link #relativeTime(OffsetDateTime)} is used if {@code parsed != null}, otherwise
380- * {@code textual} is returned. If in debug mode, {@code context != null},
381- * {@code parsed != null} and the relevant setting is enabled, {@code textual} will
397+ * @param textual the original textual date or time ago string as provided by
398+ * services
399+ * @return {@link #relativeTime(OffsetDateTime)} is used if
400+ * {@code parsed != null}, otherwise
401+ * {@code textual} is returned. If in debug mode,
402+ * {@code context != null},
403+ * {@code parsed != null} and the relevant setting is enabled,
404+ * {@code textual} will
382405 * be appended to the returned string for debugging purposes.
383406 */
384407 public static String relativeTimeOrTextual (@ Nullable final Context context ,
385- @ Nullable final DateWrapper parsed ,
386- final String textual ) {
408+ @ Nullable final DateWrapper parsed ,
409+ final String textual ) {
387410 if (parsed == null ) {
388411 return textual ;
389412 } else if (DEBUG && context != null && PreferenceManager
@@ -404,7 +427,7 @@ public static void assureCorrectAppLanguage(final Context c) {
404427 }
405428
406429 private static Locale getLocaleFromPrefs (@ NonNull final Context context ,
407- @ StringRes final int prefKey ) {
430+ @ StringRes final int prefKey ) {
408431 final SharedPreferences sp = PreferenceManager .getDefaultSharedPreferences (context );
409432 final String defaultKey = context .getString (R .string .default_localization_key );
410433 final String languageCode = sp .getString (context .getString (prefKey ), defaultKey );
@@ -421,10 +444,10 @@ private static double round(final double value) {
421444 }
422445
423446 private static String getQuantity (@ NonNull final Context context ,
424- @ PluralsRes final int pluralId ,
425- @ StringRes final int zeroCaseStringId ,
426- final long count ,
427- final String formattedCount ) {
447+ @ PluralsRes final int pluralId ,
448+ @ StringRes final int zeroCaseStringId ,
449+ final long count ,
450+ final String formattedCount ) {
428451 if (count == 0 ) {
429452 return context .getString (zeroCaseStringId );
430453 }
0 commit comments