Multiple localization fixes

With the extractor PR, fixes title & description shown in the wrong language.
Fixed views / spectators counts possibly in the wrong language
Fixed live spectators not showing full count on detail page
Fixed LIVE shown on players, it shows translated instead

Fixed Videos string in search / three dots not available in Weblate
(because it was videos, but there already was a plural string named videos, in Weblate)

Subscriber count is always giving the short count.
We can't get exact number since this YouTube update: https://support.google.com/youtube/thread/6543166
But only short count (B, M, k), so showing full number, eg for 1.9M: 1,900,000, is wrong because the number could be 1,923,490 or 1,897,789…

Added a « sytem default » option to content language and country language selector.
It's the one selected by default (not en-GB anymore then), and correspond to the
language of the system / country of the system
By system I mean phone, tablet, TV…

Fixed russian showing - before time ago (eg 19hrs ago)
This is a workaround fix, I opened an issue on prettytime library repo.

Fixed russian plurals:
other was used instead of many for videos and subscribers

Fixed seek_duration english only
This commit is contained in:
bopol 2020-02-14 18:19:35 +01:00
parent ec45d4a729
commit f089cd027e
16 changed files with 59 additions and 42 deletions

View file

@ -63,7 +63,7 @@ dependencies {
exclude module: 'support-annotations' exclude module: 'support-annotations'
}) })
implementation 'com.github.TeamNewPipe:NewPipeExtractor:9112a10' implementation 'com.github.B0pol:NewPipeExtractor:a9c6beec1434f4edd4197fb655e5327bae94cc92'
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:2.23.0' testImplementation 'org.mockito:mockito-core:2.23.0'

View file

@ -1074,7 +1074,7 @@ public class VideoDetailFragment
if (info.getStreamType().equals(StreamType.AUDIO_LIVE_STREAM)) { if (info.getStreamType().equals(StreamType.AUDIO_LIVE_STREAM)) {
videoCountView.setText(Localization.listeningCount(activity, info.getViewCount())); videoCountView.setText(Localization.listeningCount(activity, info.getViewCount()));
} else if (info.getStreamType().equals(StreamType.LIVE_STREAM)) { } else if (info.getStreamType().equals(StreamType.LIVE_STREAM)) {
videoCountView.setText(Localization.watchingCount(activity, info.getViewCount())); videoCountView.setText(Localization.localizeWatchingCount(activity, info.getViewCount()));
} else { } else {
videoCountView.setText(Localization.localizeViewCount(activity, info.getViewCount())); videoCountView.setText(Localization.localizeViewCount(activity, info.getViewCount()));
} }

View file

@ -370,7 +370,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
headerSubscribersTextView.setVisibility(View.VISIBLE); headerSubscribersTextView.setVisibility(View.VISIBLE);
if (result.getSubscriberCount() >= 0) { if (result.getSubscriberCount() >= 0) {
headerSubscribersTextView.setText(Localization.localizeSubscribersCount(activity, result.getSubscriberCount())); headerSubscribersTextView.setText(Localization.shortSubscriberCount(activity, result.getSubscriberCount()));
} else { } else {
headerSubscribersTextView.setText(R.string.subscribers_count_not_available); headerSubscribersTextView.setText(R.string.subscribers_count_not_available);
} }

View file

@ -60,7 +60,7 @@ public class StreamInfoItemHolder extends StreamMiniInfoItemHolder {
if (infoItem.getStreamType().equals(StreamType.AUDIO_LIVE_STREAM)) { if (infoItem.getStreamType().equals(StreamType.AUDIO_LIVE_STREAM)) {
viewsAndDate = Localization.listeningCount(itemBuilder.getContext(), infoItem.getViewCount()); viewsAndDate = Localization.listeningCount(itemBuilder.getContext(), infoItem.getViewCount());
} else if (infoItem.getStreamType().equals(StreamType.LIVE_STREAM)) { } else if (infoItem.getStreamType().equals(StreamType.LIVE_STREAM)) {
viewsAndDate = Localization.watchingCount(itemBuilder.getContext(), infoItem.getViewCount()); viewsAndDate = Localization.shortWatchingCount(itemBuilder.getContext(), infoItem.getViewCount());
} else { } else {
viewsAndDate = Localization.shortViewCount(itemBuilder.getContext(), infoItem.getViewCount()); viewsAndDate = Localization.shortViewCount(itemBuilder.getContext(), infoItem.getViewCount());
} }

View file

@ -4,9 +4,9 @@ import android.content.SharedPreferences;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings; import android.provider.Settings;
import android.view.View;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.preference.ListPreference;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
@ -21,6 +21,16 @@ public class VideoAudioSettingsFragment extends BasePreferenceFragment {
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
String[] durationsDescriptions = getResources().getStringArray(R.array.seek_duration_description);
String[] durationsValues = getResources().getStringArray(R.array.seek_duration_value);
int currentDurationValue;
for (int i = 0; i < durationsDescriptions.length; i++) {
currentDurationValue = Integer.parseInt(durationsValues[i]) / 1000;
durationsDescriptions[i] = String.format(durationsDescriptions[i], currentDurationValue);
}
ListPreference durations = (ListPreference) findPreference(getString(R.string.seek_duration_key));
durations.setEntries(durationsDescriptions);
listener = (sharedPreferences, s) -> { listener = (sharedPreferences, s) -> {
// on M and above, if user chooses to minimise to popup player on exit and the app doesn't have // on M and above, if user chooses to minimise to popup player on exit and the app doesn't have

View file

@ -48,8 +48,8 @@ import java.util.Locale;
public class Localization { public class Localization {
private static PrettyTime prettyTime;
private static final String DOT_SEPARATOR = ""; private static final String DOT_SEPARATOR = "";
private static PrettyTime prettyTime;
private Localization() { private Localization() {
} }
@ -84,6 +84,9 @@ public class Localization {
final String contentLanguage = PreferenceManager final String contentLanguage = PreferenceManager
.getDefaultSharedPreferences(context) .getDefaultSharedPreferences(context)
.getString(context.getString(R.string.content_language_key), context.getString(R.string.default_language_value)); .getString(context.getString(R.string.content_language_key), context.getString(R.string.default_language_value));
if (contentLanguage.equals("system")) {
return org.schabi.newpipe.extractor.localization.Localization.fromLocale(Locale.getDefault());
}
return org.schabi.newpipe.extractor.localization.Localization.fromLocalizationCode(contentLanguage); return org.schabi.newpipe.extractor.localization.Localization.fromLocalizationCode(contentLanguage);
} }
@ -91,6 +94,9 @@ public class Localization {
final String contentCountry = PreferenceManager final String contentCountry = PreferenceManager
.getDefaultSharedPreferences(context) .getDefaultSharedPreferences(context)
.getString(context.getString(R.string.content_country_key), context.getString(R.string.default_country_value)); .getString(context.getString(R.string.content_country_key), context.getString(R.string.default_country_value));
if (contentCountry.equals("system")) {
return new ContentCountry(Locale.getDefault().getCountry());
}
return new ContentCountry(contentCountry); return new ContentCountry(contentCountry);
} }
@ -114,8 +120,7 @@ public class Localization {
} }
public static String localizeNumber(Context context, long number) { public static String localizeNumber(Context context, long number) {
Locale locale = getPreferredLocale(context); NumberFormat nf = NumberFormat.getInstance(getAppLocale(context));
NumberFormat nf = NumberFormat.getInstance(locale);
return nf.format(number); return nf.format(number);
} }
@ -132,14 +137,14 @@ public class Localization {
return getQuantity(context, R.plurals.views, R.string.no_views, viewCount, localizeNumber(context, viewCount)); return getQuantity(context, R.plurals.views, R.string.no_views, viewCount, localizeNumber(context, viewCount));
} }
public static String localizeSubscribersCount(Context context, long subscriberCount) {
return getQuantity(context, R.plurals.subscribers, R.string.no_subscribers, subscriberCount, localizeNumber(context, subscriberCount));
}
public static String localizeStreamCount(Context context, long streamCount) { public static String localizeStreamCount(Context context, long streamCount) {
return getQuantity(context, R.plurals.videos, R.string.no_videos, streamCount, localizeNumber(context, streamCount)); return getQuantity(context, R.plurals.videos, R.string.no_videos, streamCount, localizeNumber(context, streamCount));
} }
public static String localizeWatchingCount(Context context, long watchingCount) {
return getQuantity(context, R.plurals.watching, R.string.no_one_watching, watchingCount, localizeNumber(context, watchingCount));
}
public static String shortCount(Context context, long count) { public static String shortCount(Context context, long count) {
if (count >= 1000000000) { if (count >= 1000000000) {
return Long.toString(count / 1000000000) + context.getString(R.string.short_billion); return Long.toString(count / 1000000000) + context.getString(R.string.short_billion);
@ -156,7 +161,7 @@ public class Localization {
return getQuantity(context, R.plurals.listening, R.string.no_one_listening, listeningCount, shortCount(context, listeningCount)); return getQuantity(context, R.plurals.listening, R.string.no_one_listening, listeningCount, shortCount(context, listeningCount));
} }
public static String watchingCount(Context context, long watchingCount) { public static String shortWatchingCount(Context context, long watchingCount) {
return getQuantity(context, R.plurals.watching, R.string.no_one_watching, watchingCount, shortCount(context, watchingCount)); return getQuantity(context, R.plurals.watching, R.string.no_one_watching, watchingCount, shortCount(context, watchingCount));
} }
@ -215,7 +220,9 @@ public class Localization {
} }
public static String relativeTime(Calendar calendarTime) { public static String relativeTime(Calendar calendarTime) {
return getPrettyTime().formatUnrounded(calendarTime); String time = getPrettyTime().formatUnrounded(calendarTime);
return time.startsWith("-") ? time.substring(1) : time;
//workaround fix for russian showing -1 day ago, -19hrs ago
} }
private static void changeAppLanguage(Locale loc, Resources res) { private static void changeAppLanguage(Locale loc, Resources res) {
@ -226,8 +233,8 @@ public class Localization {
} }
public static Locale getAppLocale(Context context) { public static Locale getAppLocale(Context context) {
SharedPreferences prefs = androidx.preference.PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String lang = prefs.getString("app_language_key", "en"); String lang = prefs.getString(context.getString(R.string.app_language_key), "en");
Locale loc; Locale loc;
if (lang.equals("system")) { if (lang.equals("system")) {
loc = Locale.getDefault(); loc = Locale.getDefault();

View file

@ -44,7 +44,7 @@ public class ServiceHelper {
public static String getTranslatedFilterString(String filter, Context c) { public static String getTranslatedFilterString(String filter, Context c) {
switch (filter) { switch (filter) {
case "all": return c.getString(R.string.all); case "all": return c.getString(R.string.all);
case "videos": return c.getString(R.string.videos); case "videos": return c.getString(R.string.videos_string);
case "channels": return c.getString(R.string.channels); case "channels": return c.getString(R.string.channels);
case "playlists": return c.getString(R.string.playlists); case "playlists": return c.getString(R.string.playlists);
case "tracks": return c.getString(R.string.tracks); case "tracks": return c.getString(R.string.tracks);

View file

@ -304,10 +304,9 @@
android:paddingLeft="4dp" android:paddingLeft="4dp"
android:paddingRight="4dp" android:paddingRight="4dp"
android:gravity="center" android:gravity="center"
android:text="@string/duration_live_button" android:text="@string/duration_live"
android:textAllCaps="true" android:textAllCaps="true"
android:textColor="?attr/colorAccent" android:textColor="?attr/colorAccent"
android:maxLength="4"
android:background="?attr/selectableItemBackground" android:background="?attr/selectableItemBackground"
android:visibility="gone"/> android:visibility="gone"/>
</LinearLayout> </LinearLayout>

View file

@ -442,10 +442,9 @@
android:paddingLeft="4dp" android:paddingLeft="4dp"
android:paddingRight="4dp" android:paddingRight="4dp"
android:gravity="center" android:gravity="center"
android:text="@string/duration_live_button" android:text="@string/duration_live"
android:textAllCaps="true" android:textAllCaps="true"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:maxLength="4"
android:visibility="gone" android:visibility="gone"
android:background="?attr/selectableItemBackground" android:background="?attr/selectableItemBackground"
tools:ignore="HardcodedText,RtlHardcoded,RtlSymmetry" /> tools:ignore="HardcodedText,RtlHardcoded,RtlSymmetry" />

View file

@ -440,10 +440,9 @@
android:paddingLeft="4dp" android:paddingLeft="4dp"
android:paddingRight="4dp" android:paddingRight="4dp"
android:gravity="center" android:gravity="center"
android:text="@string/duration_live_button" android:text="@string/duration_live"
android:textAllCaps="true" android:textAllCaps="true"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:maxLength="4"
android:visibility="gone" android:visibility="gone"
android:background="?attr/selectableItemBackground" android:background="?attr/selectableItemBackground"
tools:ignore="HardcodedText,RtlHardcoded,RtlSymmetry" /> tools:ignore="HardcodedText,RtlHardcoded,RtlSymmetry" />

View file

@ -154,10 +154,9 @@
android:paddingLeft="4dp" android:paddingLeft="4dp"
android:paddingRight="4dp" android:paddingRight="4dp"
android:gravity="center" android:gravity="center"
android:text="@string/duration_live_button" android:text="@string/duration_live"
android:textAllCaps="true" android:textAllCaps="true"
android:textColor="?attr/colorAccent" android:textColor="?attr/colorAccent"
android:maxLength="4"
android:background="?attr/selectableItemBackground" android:background="?attr/selectableItemBackground"
android:visibility="gone"/> android:visibility="gone"/>
</LinearLayout> </LinearLayout>

View file

@ -208,10 +208,9 @@
android:paddingLeft="4dp" android:paddingLeft="4dp"
android:paddingRight="4dp" android:paddingRight="4dp"
android:gravity="center_vertical" android:gravity="center_vertical"
android:text="@string/duration_live_button" android:text="@string/duration_live"
android:textAllCaps="true" android:textAllCaps="true"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:maxLength="4"
android:visibility="gone" android:visibility="gone"
android:background="?attr/selectableItemBackground" android:background="?attr/selectableItemBackground"
tools:ignore="HardcodedText,RtlHardcoded,RtlSymmetry" /> tools:ignore="HardcodedText,RtlHardcoded,RtlSymmetry" />

View file

@ -537,4 +537,6 @@
<string name="clear_download_history">Forviŝi la historion de elŝutoj</string> <string name="clear_download_history">Forviŝi la historion de elŝutoj</string>
<string name="delete_downloaded_files">Forviŝi elŝutitajn dosierojn</string> <string name="delete_downloaded_files">Forviŝi elŝutitajn dosierojn</string>
<string name="deleted_downloads">%1$s elŝutoj forviŝitaj</string> <string name="deleted_downloads">%1$s elŝutoj forviŝitaj</string>
<string name="videos_string">Filmetoj</string>
<string name="dynamic_seek_duration_description">%s sekundoj</string>
</resources> </resources>

View file

@ -201,13 +201,13 @@
<plurals name="subscribers"> <plurals name="subscribers">
<item quantity="one">%s подписчик</item> <item quantity="one">%s подписчик</item>
<item quantity="few">%s подписчика</item> <item quantity="few">%s подписчика</item>
<item quantity="other">%s подписчиков</item> <item quantity="many">%s подписчиков</item>
</plurals> </plurals>
<string name="no_views">Нет просмотров</string> <string name="no_views">Нет просмотров</string>
<plurals name="views"> <plurals name="views">
<item quantity="one">%s просмотр</item> <item quantity="one">%s просмотр</item>
<item quantity="few">%s просмотра</item> <item quantity="few">%s просмотра</item>
<item quantity="other">%s просмотров</item> <item quantity="many">%s просмотров</item>
</plurals> </plurals>
<string name="no_videos">Нет видео</string> <string name="no_videos">Нет видео</string>
<plurals name="videos"> <plurals name="videos">

View file

@ -31,12 +31,12 @@
<string name="seek_duration_key" translatable="false">seek_duration</string> <string name="seek_duration_key" translatable="false">seek_duration</string>
<string name="seek_duration_default_value" translatable="false">10000</string> <string name="seek_duration_default_value" translatable="false">10000</string>
<string-array name="seek_duration_description" translatable="false"> <string-array name="seek_duration_description" translatable="false">
<item>5 seconds</item> <item>@string/dynamic_seek_duration_description</item>
<item>10 seconds</item> <item>@string/dynamic_seek_duration_description</item>
<item>15 seconds</item> <item>@string/dynamic_seek_duration_description</item>
<item>20 seconds</item> <item>@string/dynamic_seek_duration_description</item>
<item>25 seconds</item> <item>@string/dynamic_seek_duration_description</item>
<item>30 seconds</item> <item>@string/dynamic_seek_duration_description</item>
</string-array> </string-array>
<string-array name="seek_duration_value" translatable="false"> <string-array name="seek_duration_value" translatable="false">
<item>5000</item> <item>5000</item>
@ -161,8 +161,8 @@
<string name="show_comments_key" translatable="false">show_comments</string> <string name="show_comments_key" translatable="false">show_comments</string>
<string name="stream_info_selected_tab_key" translatable="false">stream_info_selected_tab</string> <string name="stream_info_selected_tab_key" translatable="false">stream_info_selected_tab</string>
<string name="show_hold_to_append_key" translatable="false">show_hold_to_append</string> <string name="show_hold_to_append_key" translatable="false">show_hold_to_append</string>
<string name="default_language_value">en</string> <string name="default_language_value" translatable="false">system</string>
<string name="default_country_value">GB</string> <string name="default_country_value" translatable="false">system</string>
<string name="content_language_key" translatable="false">content_language</string> <string name="content_language_key" translatable="false">content_language</string>
<string name="peertube_instance_setup_key" translatable="false">peertube_instance_setup</string> <string name="peertube_instance_setup_key" translatable="false">peertube_instance_setup</string>
<string name="peertube_selected_instance_key" translatable="false">peertube_selected_instance</string> <string name="peertube_selected_instance_key" translatable="false">peertube_selected_instance</string>
@ -267,6 +267,7 @@
<!-- alternatively, load these from some local android data store --> <!-- alternatively, load these from some local android data store -->
<string-array name="language_codes" translatable="false"> <string-array name="language_codes" translatable="false">
<item>system</item>
<item>af</item> <item>af</item>
<item>az</item> <item>az</item>
<item>id</item> <item>id</item>
@ -346,6 +347,7 @@
<item>ko</item> <item>ko</item>
</string-array> </string-array>
<string-array name="language_names" translatable="false"> <string-array name="language_names" translatable="false">
<item>@string/system_default</item>
<item>Afrikaans</item> <item>Afrikaans</item>
<item>Azərbaycan</item> <item>Azərbaycan</item>
<item>Bahasa Indonesia</item> <item>Bahasa Indonesia</item>
@ -427,6 +429,7 @@
<string-array name="country_names" translatable="false"> <string-array name="country_names" translatable="false">
<item>@string/system_default</item>
<item>Afghanistan</item> <item>Afghanistan</item>
<item>Aland Islands</item> <item>Aland Islands</item>
<item>Albania</item> <item>Albania</item>
@ -677,6 +680,7 @@
</string-array> </string-array>
<string-array name="country_codes" translatable="false"> <string-array name="country_codes" translatable="false">
<item>system</item>
<item>AF</item> <item>AF</item>
<item>AX</item> <item>AX</item>
<item>AL</item> <item>AL</item>
@ -993,7 +997,7 @@
<item>zh-tw</item> <item>zh-tw</item>
</string-array> </string-array>
<string-array name="app_language_name" translatable="false"> <string-array name="app_language_name" translatable="false">
<item>@string/systems_language</item> <item>@string/system_default</item>
<item>العربية</item> <item>العربية</item>
<item>Azərbaycan dili</item> <item>Azərbaycan dili</item>
<item>Asturianu</item> <item>Asturianu</item>

View file

@ -140,7 +140,6 @@
<string name="show_age_restricted_content_title">Age restricted content</string> <string name="show_age_restricted_content_title">Age restricted content</string>
<string name="video_is_age_restricted">Show age restricted video. Allowing such material is possible from Settings.</string> <string name="video_is_age_restricted">Show age restricted video. Allowing such material is possible from Settings.</string>
<string name="duration_live">LIVE</string> <string name="duration_live">LIVE</string>
<string name="duration_live_button" translatable="false">LIVE</string>
<string name="downloads">Downloads</string> <string name="downloads">Downloads</string>
<string name="downloads_title">Downloads</string> <string name="downloads_title">Downloads</string>
<string name="error_report_title">Error report</string> <string name="error_report_title">Error report</string>
@ -149,8 +148,7 @@
<string name="channels">Channels</string> <string name="channels">Channels</string>
<string name="playlist">Playlist</string> <string name="playlist">Playlist</string>
<string name="playlists">Playlists</string> <string name="playlists">Playlists</string>
<string name="videos">Videos</string> <string name="videos_string">Videos</string>
<string name="comments">Comments</string>
<string name="tracks">Tracks</string> <string name="tracks">Tracks</string>
<string name="users">Users</string> <string name="users">Users</string>
<string name="events">Events</string> <string name="events">Events</string>
@ -593,5 +591,6 @@
<string name="downloads_storage_use_saf_summary">The Storage Access Framework allows downloads to an external SD card.\nNote: some devices are not compatible</string> <string name="downloads_storage_use_saf_summary">The Storage Access Framework allows downloads to an external SD card.\nNote: some devices are not compatible</string>
<string name="choose_instance_prompt">Choose an instance</string> <string name="choose_instance_prompt">Choose an instance</string>
<string name="app_language_title">App language</string> <string name="app_language_title">App language</string>
<string name="systems_language">System default</string> <string name="system_default">System default</string>
<string name="dynamic_seek_duration_description">%s seconds</string>
</resources> </resources>