🌐 Add i18n and let View handle formatting

Alexis Drai 2 years ago
parent d07e35d12c
commit 8dfab2df0d

@ -1,4 +1,6 @@
namespace AMC.View;
using System.Globalization;
namespace AMC.View;
public partial class App : Application
{
@ -8,4 +10,14 @@ public partial class App : Application
MainPage = new AppShell();
}
protected override void OnStart()
{
base.OnStart();
// Uncomment to set the culture to French
// CultureInfo.CurrentCulture = new CultureInfo("fr-FR");
// CultureInfo.CurrentUICulture = new CultureInfo("fr-FR");
}
}

@ -0,0 +1,22 @@
using System.Globalization;
namespace AMC.View.Converters
{
public class AlbumDetailsConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var (genre, year) = (ValueTuple<string, int>)value;
return string.Format(
"{0} · {1}",
genre,
year
);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

@ -0,0 +1,22 @@
using System.Globalization;
namespace AMC.View.Converters
{
public class CopyrightInfoConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var (copyrightYear, producerBlurb) = (ValueTuple<int, string>)value;
return string.Format(
"℗ {0} {1}",
copyrightYear,
producerBlurb
);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

@ -0,0 +1,27 @@
using AMC.View.Resources.Strings;
using System.Globalization;
namespace AMC.View.Converters
{
public class SongsInfoConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var (songCount, totalDuration) = (ValueTuple<int, int>)value;
var songLabel = songCount == 1 ? Strings.SongsLabelSingular : Strings.SongsLabelPlural;
var minutesLabel = totalDuration == 1 ? Strings.MinutesLabelSingular : Strings.MinutesLabelPlural;
return string.Format(
"{0} {1}, {2} {3}",
songCount,
songLabel,
totalDuration,
minutesLabel
);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

@ -60,6 +60,33 @@ namespace AMC.View.Resources.Strings {
}
}
/// <summary>
/// Looks up a localized string similar to Library.
/// </summary>
public static string LibraryTitle {
get {
return ResourceManager.GetString("LibraryTitle", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to minutes.
/// </summary>
public static string MinutesLabelPlural {
get {
return ResourceManager.GetString("MinutesLabelPlural", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to minute.
/// </summary>
public static string MinutesLabelSingular {
get {
return ResourceManager.GetString("MinutesLabelSingular", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Play.
/// </summary>
@ -77,5 +104,23 @@ namespace AMC.View.Resources.Strings {
return ResourceManager.GetString("ShuffleButton", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to songs.
/// </summary>
public static string SongsLabelPlural {
get {
return ResourceManager.GetString("SongsLabelPlural", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to song.
/// </summary>
public static string SongsLabelSingular {
get {
return ResourceManager.GetString("SongsLabelSingular", resourceCulture);
}
}
}
}

@ -123,4 +123,19 @@
<data name="ShuffleButton" xml:space="preserve">
<value>Aléatoire</value>
</data>
<data name="LibraryTitle" xml:space="preserve">
<value>Bibliothèque</value>
</data>
<data name="SongsLabelPlural" xml:space="preserve">
<value>morceaux</value>
</data>
<data name="MinutesLabelPlural" xml:space="preserve">
<value>minutes</value>
</data>
<data name="SongsLabelSingular" xml:space="preserve">
<value>morceau</value>
</data>
<data name="MinutesLabelSingular" xml:space="preserve">
<value>minute</value>
</data>
</root>

@ -123,4 +123,19 @@
<data name="ShuffleButton" xml:space="preserve">
<value>Shuffle</value>
</data>
<data name="LibraryTitle" xml:space="preserve">
<value>Library</value>
</data>
<data name="SongsLabelPlural" xml:space="preserve">
<value>songs</value>
</data>
<data name="MinutesLabelPlural" xml:space="preserve">
<value>minutes</value>
</data>
<data name="SongsLabelSingular" xml:space="preserve">
<value>song</value>
</data>
<data name="MinutesLabelSingular" xml:space="preserve">
<value>minute</value>
</data>
</root>

@ -3,9 +3,18 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:AMC.View"
xmlns:strings="clr-namespace:AMC.View.Resources.Strings"
xmlns:conv="clr-namespace:AMC.View.Converters"
xmlns:vm="clr-namespace:AMC.ViewModel.ViewModels;assembly=AMC.ViewModel"
x:Class="AMC.View.Views.AlbumPage"
x:DataType="vm:AlbumViewModel">
<ContentPage.Resources>
<ResourceDictionary>
<conv:SongsInfoConverter x:Key="SongsInfo" />
<conv:CopyrightInfoConverter x:Key="CopyrightInfo" />
<conv:AlbumDetailsConverter x:Key="AlbumDetails" />
</ResourceDictionary>
</ContentPage.Resources>
<ScrollView BackgroundColor="{AppThemeBinding Light={StaticResource Background}, Dark={StaticResource BackgroundDark}}">
<Grid Margin="10">
@ -41,7 +50,7 @@
</StackLayout>
<StackLayout Grid.Row="2">
<Label Text="{Binding Details}"
<Label Text="{Binding Details, Converter={StaticResource AlbumDetails}}"
FontSize="12"
TextColor="{StaticResource Gray}"
HorizontalTextAlignment="Center"/>
@ -115,15 +124,15 @@
</CollectionView.ItemTemplate>
</CollectionView>
<Label Text="{Binding ReleaseDate}"
<Label Text="{Binding ReleaseDate, StringFormat='{0:d MMMM yyyy}'}"
Style="{StaticResource FooterLabel}"
Grid.Row="5" />
<Label Text="{Binding SongsInfo}"
<Label Text="{Binding SongsInfo, Converter={StaticResource SongsInfo}}"
Style="{StaticResource FooterLabel}"
Grid.Row="6" />
<Label Text="{Binding CopyrightInfo}"
<Label Text="{Binding CopyrightInfo, Converter={StaticResource CopyrightInfo}}"
Style="{StaticResource FooterLabel}"
Grid.Row="7" />
</Grid>

@ -18,13 +18,15 @@ namespace AMC.ViewModel.ViewModels
public string CoverImage => album.CoverImage;
public string Details => $"{album.Genre} · {album.Year}";
public (string Genre, int Year) Details => (album.Genre, album.Year);
public string ReleaseDate => album.ReleaseDate.ToString("d MMMM yyyy");
public DateTime ReleaseDate => album.ReleaseDate;
public string SongsInfo => $"{album.Songs.Count} songs, {album.Songs.Sum(song => song.Duration) / 60} minutes";
public (int SongCount, int TotalDuration) SongsInfo
=> (album.Songs.Count, album.Songs.Sum(song => song.Duration) / 60);
public string CopyrightInfo => $"℗ {album.CopyrightYear} {album.ProducerBlurb}";
public (int CopyrightYear, string ProducerBlurb) CopyrightInfo
=> (album.CopyrightYear, album.ProducerBlurb);
public ReadOnlyObservableCollection<SongViewModel> Songs => new(songs);

Loading…
Cancel
Save