1

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;
  }
}
Pavel Anikhouski
  • 21,776
  • 12
  • 51
  • 66
Zohnya
  • 25
  • 1
  • 7
  • 2
    You may want to use resx files. https://learn.microsoft.com/en-us/dotnet/framework/resources/working-with-resx-files-programmatically See also this question: https://stackoverflow.com/questions/1142802/how-to-use-localization-in-c-sharp – Lucas Dec 17 '19 at 14:19
  • 2
    you can google C# i18N or C# internationalization which will show you how to use resx to translate into different languages. – phonemyatt Dec 17 '19 at 14:22
  • What does "different things" mean? Do you want to translate days or other "things" as well? There isn't a one stop shop that just "does translation" – Liam Dec 17 '19 at 14:23
  • You probably want to use standardized [language codes](http://www.loc.gov/standards/iso639-2/php/code_list.php) or the culture info codes directly (like "en" or "en-US" or "de-DE"; see [example](https://dotnetfiddle.net/e1BX7M)), to make your life easier. – Corak Dec 17 '19 at 14:28
  • So you don't want `French, English, ...` passed in as arguments from an Enum. Why do you find this a troublesome approach? – Train Dec 17 '19 at 14:37
  • @Train, i was looking for a kind of 'enum' in which you can have the abbreviated Day as index and the different languages as value. I tried to find enum with arguments but cannot find something about it. (i started C# like 3 weeks ago and tbh i probably missed the information i needed) – Zohnya Dec 17 '19 at 14:43
  • 1
    So you want a `dictionary`? To have a key value pair like `"MO", ["Monday", "Montag", ...]` Am I correct in this assumption? – Train Dec 17 '19 at 14:46
  • this might do the trick in my case but i was wondering, if we need to add 1 more language, this'll be not easy to keep up to date, right ? (i'm currently seeing the resx files and i think that's something i want to use, @LucasHarskamp, thx for the tips) – Zohnya Dec 17 '19 at 14:57
  • @Zohnya please, have a look at the last snippet in my answer, it might be helpful – Pavel Anikhouski Dec 17 '19 at 15:08
  • 1
    @Zohnya The trick is ensuring that all resx files maintain the same keywords and also that they aren't missing any keywords. Companies that use resx for localization usually create procedures that ensure that updated resx files cannot be merged into a main repository unless the requirements are being met. You could create such a standard for yourself. – Lucas Dec 17 '19 at 15:08

3 Answers3

5

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) });
        }
    }
}
Pavel Anikhouski
  • 21,776
  • 12
  • 51
  • 66
  • 1
    I'm a little confused and also worried about the up-votes, how this answers the question as the `AbbreviatedDayNames` gives you the three-letter Abbreviation name(from the link you shared) for each day and the OP is asking for the localized names. correct me if i'm wrong – sujith karivelil Dec 17 '19 at 14:29
  • @sujithkarivelil `GetDayName` returns full day name, as per answer update – Pavel Anikhouski Dec 17 '19 at 14:37
  • Thanks, it was usefull. but i have a question. Does it exist the same thing for Month ? @PavelAnikhouski – Zohnya Dec 18 '19 at 14:43
  • 1
    @Zohnya yes, of course, it exists. You can use `AbbreviatedMonthNames` property and `GetMonthName` method on the same way. I can update an answer, if needed – Pavel Anikhouski Dec 18 '19 at 15:00
2

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.

0

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))
    });
}
Innat3
  • 3,561
  • 2
  • 11
  • 29