Zohnya
Zohnya

Reputation: 25

What is the best way to translate things (i.e Days)

I'm currently trying to translate different things into different languages in C#. I'm sure there's a best way to do this than the way i'm currently using. I searched in the Enumeration Documentation but does not really found what i was looking for. I want the index in English but the value in the language i pass as argument. Does it exist a way to have this in like.. one line ?

i.e. day("MO" : fr="lundi", eng="monday", de="montag") or something equivalent (i'm open to suggestions)

private void SetDays(string language)
{
  switch(language)
    {
    case "french":
      days.Add( "MO", "lundi");
      days.Add( "TU", "mardi" );
      days.Add( "WE", "mercredi" );
      days.Add( "TH", "jeudi" );
      days.Add( "FR", "vendredi" );
      days.Add( "SA", "samedi" );
      days.Add( "SU", "dimanche" );
      break;
    case "english":
      days.Add( "MO", "monday" );
      days.Add( "TU", "tuesday" );
      days.Add( "WE", "wednesday" );
      days.Add( "TH", "thursday" );
      days.Add( "FR", "friday" );
      days.Add( "SA", "saturday" );
      days.Add( "SU", "sunday" );
      break;
    case "german":
      days.Add( "MO", "montag" );
      days.Add( "TU", "dienstag" );
      days.Add( "WE", "mittwoch" );
      days.Add( "TH", "donnerstag" );
      days.Add( "FR", "freitag" );
      days.Add( "SA", "samstag" );
      days.Add( "SU", "sonntag" );
      break;
    default:
       //Fixme what do we do in this default case ?
      break;
  }
}

Upvotes: 1

Views: 1528

Answers (3)

Pavel Anikhouski
Pavel Anikhouski

Reputation: 23258

You can create CultureInfo object based on language and use DateTimeFormat property of this object. There is AbbreviatedDayNames property, which contains weekday names. The code snippet can be the following

CultureInfo ci = CultureInfo.CreateSpecificCulture("fr");
DateTimeFormatInfo dtfi = ci.DateTimeFormat;
var dayNames = dtfi.AbbreviatedDayNames;
var dayName = dtfi.GetDayName(DayOfWeek.Monday);

Please, keep in mind the remarks section of CreateSpecificCulture. The supported culture tags depend on used OS version (Windows 10 or earlier)

Another option is to use GetDayName, which returns the full day name based on DayOfWeek value (like on sample above). Both options (depending on your requirements) are easier, than maintaining day names manually.

If there is a need to store the day names in dictionary, it'll make sense to use some kind of code below. Using DayOfWeek is key is more easier, than string. The result dictionary contains the list of localized day names for every passed language, available by key

var dictionary = new Dictionary<DayOfWeek, List<string>>();
AddDayNames("en");
AddDayNames("de");
AddDayNames("fr");

void AddDayNames(string language)
{
    CultureInfo ci = CultureInfo.CreateSpecificCulture(language);
    DateTimeFormatInfo dtfi = ci.DateTimeFormat;

    foreach (DayOfWeek day in Enum.GetValues(typeof(DayOfWeek)))
    {
        if (dictionary.ContainsKey(day))
            dictionary[day].Add(dtfi.GetDayName(day));
        else
        {
            dictionary.Add(day, new List<string> { dtfi.GetDayName(day) });
        }
    }
}

If you want to do the same for months, this code will be helpful - using abbreviated invariant month name as key and list of culture specific month names as a value

void AddMonthNames(string language)
{
    CultureInfo ci = CultureInfo.CreateSpecificCulture(language);
    DateTimeFormatInfo dtfi = ci.DateTimeFormat;

    for (int i = 1; i <= 12; i++)
    {
        var month = CultureInfo.InvariantCulture.DateTimeFormat.GetAbbreviatedMonthName(i);
        if (dictionary.ContainsKey(month))
            dictionary[month].Add(dtfi.GetMonthName(i));
        else
        {
            dictionary.Add(month, new List<string> { dtfi.GetMonthName(i) });
        }
    }
}

Upvotes: 5

Innat3
Innat3

Reputation: 3576

Here's a way to do it:

First create an enum with the languages you want, using their ISO 639-1 Code

public enum Language
{
    FR, //French
    EN, //English
    DE  //German
}

Then create a custom class to store the translations in your desired format, for example:

public class Translation
{
    public string Key { get; set; }
    public Dictionary<Language, string> Values { get; set; }
}

The following code will store the translations of all the Languages in our Enum in the days List.

var days = new List<Translation>();

var languages = Enum.GetValues(typeof(Language)).Cast<Language>();
var cultures = languages.Select(x => x).ToDictionary(
                   k => k, 
                   v => new CultureInfo(v.ToString()).DateTimeFormat);

foreach (var dayOfWeek in Enum.GetValues(typeof(DayOfWeek)).Cast<DayOfWeek>())
{
    days.Add(new Translation()
    {
        Key = cultures[Language.EN].GetAbbreviatedDayName(dayOfWeek),
        Values = languages.ToDictionary(k => k, v => cultures[v].GetDayName(dayOfWeek))
    });
}

Upvotes: 0

David James Smith
David James Smith

Reputation: 81

Resx files are the best approach, however this amended method sets the collection as per the original question.

private void SetDays(string name)
{
    CultureInfo ci = CultureInfo.CreateSpecificCulture(name);
    DateTimeFormatInfo dtfi = ci.DateTimeFormat;

    string[] dayNames = dtfi.DayNames;
    string[] dayKeys = { "SU", "MO", "TU", "WE", "TH", "FR", "SA" };

    for (int dayIndex = 0; dayIndex < 7; dayIndex++)
    {
        days.Add(dayKeys[dayIndex], dayNames[dayIndex]);
    }
}

You will need to pass in a valid culture name, see this documentation.

Upvotes: 2

Related Questions