diff --git a/RELEASENOTES.md b/RELEASENOTES.md index c880d831e86..c376d3165de 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -39,6 +39,8 @@ `Player.addListener`. * Fix initial timestamp display in `PlayerControlView` ([#9524](https://github.com/google/ExoPlayer/issues/9254)). + * Fix capitalization of languages in the track selector + ([#9452](https://github.com/google/ExoPlayer/issues/9452)). * Extractors: * MP4: Correctly handle HEVC tracks with pixel aspect ratios other than 1. * TS: Correctly handle HEVC tracks with pixel aspect ratios other than 1. diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java b/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java index e5bd28aca23..27a0d936702 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java @@ -2243,6 +2243,11 @@ public static String[] getSystemLanguageCodes() { return systemLocales; } + /** Returns the default {@link Locale.Category#DISPLAY DISPLAY} {@link Locale}. */ + public static Locale getDefaultDisplayLocale() { + return Util.SDK_INT >= 24 ? Locale.getDefault(Locale.Category.DISPLAY) : Locale.getDefault(); + } + /** * Uncompresses the data in {@code input}. * diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTrackNameProvider.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTrackNameProvider.java index a3d20eadb7d..59fde6950f5 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTrackNameProvider.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTrackNameProvider.java @@ -17,6 +17,7 @@ import android.content.res.Resources; import android.text.TextUtils; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.util.Assertions; @@ -100,12 +101,26 @@ private String buildLabelString(Format format) { } private String buildLanguageString(Format format) { - String language = format.language; + @Nullable String language = format.language; if (TextUtils.isEmpty(language) || C.LANGUAGE_UNDETERMINED.equals(language)) { return ""; } - Locale locale = Util.SDK_INT >= 21 ? Locale.forLanguageTag(language) : new Locale(language); - return locale.getDisplayName(); + Locale languageLocale = + Util.SDK_INT >= 21 ? Locale.forLanguageTag(language) : new Locale(language); + Locale displayLocale = Util.getDefaultDisplayLocale(); + String languageName = languageLocale.getDisplayName(displayLocale); + if (TextUtils.isEmpty(languageName)) { + return ""; + } + try { + // Capitalize the first letter. See: https://github.com/google/ExoPlayer/issues/9452. + int firstCodePointLength = languageName.offsetByCodePoints(0, 1); + return languageName.substring(0, firstCodePointLength).toUpperCase(displayLocale) + + languageName.substring(firstCodePointLength); + } catch (IndexOutOfBoundsException e) { + // Should never happen, but return the unmodified language name if it does. + return languageName; + } } private String buildRoleString(Format format) { diff --git a/library/ui/src/test/java/com/google/android/exoplayer2/ui/DefaultTrackNameProviderTest.java b/library/ui/src/test/java/com/google/android/exoplayer2/ui/DefaultTrackNameProviderTest.java new file mode 100644 index 00000000000..a5ea81f2597 --- /dev/null +++ b/library/ui/src/test/java/com/google/android/exoplayer2/ui/DefaultTrackNameProviderTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2.ui; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.res.Resources; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.Format; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Tests for the {@link DefaultMediaDescriptionAdapter}. */ +@RunWith(AndroidJUnit4.class) +public class DefaultTrackNameProviderTest { + + @Test + public void getTrackName_handlesInvalidLanguage() { + Resources resources = ApplicationProvider.getApplicationContext().getResources(); + DefaultTrackNameProvider provider = new DefaultTrackNameProvider(resources); + Format format = new Format.Builder().setLanguage("```").build(); + + String name = provider.getTrackName(format); + + assertThat(name).isEqualTo(resources.getString(R.string.exo_track_unknown)); + } +}