MfGames.Culture API - Introduction

Lately, I've been creating a C# library for handling arbitrary cultures. There is already a built-in system for this (System.Globalization), but I was hitting up against limitations that I couldn't figure out how to work around: I'm writing for cultures that doesn't exist. It is not easy to add a new country, language, or calendar into the API. That makes sense, the designers of C# probably weren't worried about people into world-building or conlangs, or having calendars that don't follow the standard “year, month, day” (YMD) cycle of the modern world.

But, in fantasy, there is a lot more variance from the YMD. Both Exalted's and Tolkien's have special weeks or days in them. There are calendars like mine that use fall days instead of leap days. Or you have large cycle calendars, like the Aztec with the Long Count. Yeah, the last one isn't fantasy, but it doesn't quite follow the YMD pattern and, therefore, doesn't show up in a lot of programming APIs.

In sci-fi, calendars may be more standardized on the YMD, but the length of the days are different. A day on Mars is forty minutes longer and a day on Jupiter is just under ten hours (thanks Google). I wouldn't be surprised if author's other worlds have similar traits. I want those calendars to also work and still be able to correspond them to a point on time here on Earth.

You also have this in fantasy, such as D&D where time travels differently on the astral and other planes.


  1. Introduction
  2. Language Codes
  3. Country Codes

My initial goals

When I write my novels and stories, I have a bunch of metadata up in the header of each chapter. I'm planning on keeping this for Author Intrusion and it is a system that I'm pretty happy with.

For example, chapter two of Sand and Blood has these entries (among others):

title: Confession
when: xmi,1471/3/28
time: 40 min

(There is some formatting issues here, sorry about that.)

The when tag tells me when in the world this event happened. I wrote it in the in-world calendar because I can use that to create a timeline. The time element is for how long the chapter is; this is a rough estimate favoring the long side, but mainly is intended to give me a block of time that I can eventually display on my website.

XKCD ISO 8601 Dates

The xmi, prefix on the date is just to avoid any parsing issues with the date. One of the largest problems I've encountered with date formatting is that many cultures use the same separators and numbers in each field, but they have different meanings. For example, in Europe “3/4/2015” means April 3rd but in the US it means March 4th. I'm planning on having this same conflict in my world, so I'm giving myself an out to avoid it in internal situations where I don't want to suffer.

Using standards

When I first decided to create a calendar, I seriously considered writing a Fedran-specific one. But, that doesn't seem to be my nature. Instead, I went with trying to use as many existing standards as possible (assuming I was aware of them) to represent my world.

Many readers may be familiar with en-US, en-GB, or fr-CA (U.S. English, British English, and Canadian French). I prefer the three-letter versions (e.g., eng-US) but that is less important. The code itself is an IEFT Language Tag which is based on both the ISO 639 Language Code and the ISO 3166 Country Codes.

The specification for all three are pretty well known, but more importantly, they support non-standard versions. That way, I can say the language of Miwāfu is xmi and the country of Kyōti is QKY.

How its used

It's a small thing, but I use these codes in my writing.

Kanéko looked over at Garèo, struggling with the words in her head before she spoke. "t-xmi: Are you `eng: sure`?".

When it is rendered by the formatter, I get this:

Kanéko looked over at Garèo, struggling with the words in her head before she spoke. "Are you sure?".

Now, this is a violation of the IEFT tag. It should be en-t-xmi or eng-t-xmi to say “Miwāfu translated into English” or notionally translated. I'm going to support t-xmi simply for typing reasons just as I'm using * to indicate the native language of the book.

If she was actually speaking the language and the POV character didn't understand it, I'd have this:

Mioráshi muttered, "xmi: oe nyozerìku," before stalking away.

Which will still render as:

Mioráshi muttered, “oe nyozerìku,” before stalking away.

But it would let me see where I write in the conlang and translate it based on characters. It also lets me use the language to figure out formatting since I use guillemets for telepathy.

The library

I'm probably over-engineering this, but it ties into my work with Author Intrusion, this library, and my ebook formatting. So, it fits my overall goals and I don't think there is an open-sourced library (or a System namespace) that quite fits my uses of it (the ability to add unknown languages and countries into the system).

XKCD The General Problem

Right now, the library consists of:

  • ISO Language Codes
  • IEFT Language Tags (missing a lot)
  • ISO Country Codes
  • Language Selectors (based on the HTTP Accept-Language header)
  • Translation Management
  • Arbitrary Calendars

Things I still have left:

  • XML and JSON reading
  • Handling Multiple Culture
  • CLI Tool


An interesting aspect about being both a writer and programmer is that I see things from different angles. One of the differences is asking for critiques. In writing, you can beg friends to do it, post on website, go to a writing group, or a number of other things. There isn't the same thing for programming and creating APIs. I haven't found a good place to see if the signatures make sense, the organization is insane, or there was already a library that does everything and more but I just missed it.

In the end, I'm going to write a short series of posts about the library, not only to let search engines know what I'm trying but also to see if I can get opinions about implementation, API surface, and the little things that I may have missed while I'm trying to get a calendar functionality built up.

All of my work for this is in the Github repository in the drem-0.0.0 branch. It is licensed with MIT and is all alpha quality, it works and I'm doing TDD for a bulk of the writing.