Here are all the LanguageWorkers currently integrated into RimWorld. If you notice any bug then please let us know!
A LanguageWorker is a piece of code which generates indefinite/definite/plural/etc. forms of words. They're handled like this because for example in some languages they depend on the gender of the noun.
Default
Catalan
Danish
Dutch
English
French
German
Hungarian
Italian
Korean
A LanguageWorker is a piece of code which generates indefinite/definite/plural/etc. forms of words. They're handled like this because for example in some languages they depend on the gender of the noun.
Default
Code Select
public abstract class LanguageWorker
{
public virtual string WithIndefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
if( str.NullOrEmpty() )
return "";
//By default names don't get articles
if( name )
return str;
if( Translator.CanTranslate( "IndefiniteForm" ) )
return "IndefiniteForm".Translate(str);
else
return "IndefiniteArticle".Translate() + " " + str;
}
public string WithIndefiniteArticle(string str, bool plural = false, bool name = false)
{
return WithIndefiniteArticle(str, LanguageDatabase.activeLanguage.ResolveGender(str), plural, name);
}
public string WithIndefiniteArticlePostProcessed(string str, Gender gender, bool plural = false, bool name = false)
{
return PostProcessed(WithIndefiniteArticle(str, gender, plural, name));
}
public string WithIndefiniteArticlePostProcessed(string str, bool plural = false, bool name = false)
{
return PostProcessed(WithIndefiniteArticle(str, plural, name));
}
public virtual string WithDefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
if( str.NullOrEmpty() )
return "";
//By default names don't get articles
if( name )
return str;
if( Translator.CanTranslate( "DefiniteForm" ) )
return "DefiniteForm".Translate(str);
else
return "DefiniteArticle".Translate() + " " + str;
}
public string WithDefiniteArticle(string str, bool plural = false, bool name = false)
{
return WithDefiniteArticle(str, LanguageDatabase.activeLanguage.ResolveGender(str), plural, name);
}
public string WithDefiniteArticlePostProcessed(string str, Gender gender, bool plural = false, bool name = false)
{
return PostProcessed(WithDefiniteArticle(str, gender, plural, name));
}
public string WithDefiniteArticlePostProcessed(string str, bool plural = false, bool name = false)
{
return PostProcessed(WithDefiniteArticle(str, plural, name));
}
public virtual string OrdinalNumber(int number, Gender gender = Gender.None)
{
return number.ToString();
}
public virtual string PostProcessed(string str)
{
//Fix double-spaces
str = str.MergeMultipleSpaces();
return str;
}
public virtual string ToTitleCase(string str)
{
if( str.NullOrEmpty() )
return str;
return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(str);
}
public virtual string Pluralize(string str, Gender gender, int count = -1)
{
return str;
}
public string Pluralize(string str, int count = -1)
{
return Pluralize(str, LanguageDatabase.activeLanguage.ResolveGender(str), count);
}
public virtual string PostProcessedKeyedTranslation(string translation)
{
return translation;
}
}
Catalan
Code Select
public class LanguageWorker_Catalan : LanguageWorker
{
public override string WithIndefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
if( name )
return WithElLaArticle(str, gender, true);
else if( plural )
return (gender == Gender.Female ? "unes " : "uns ") + str;
else
return (gender == Gender.Female ? "una " : "un ") + str;
}
public override string WithDefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
if( name )
return WithElLaArticle(str, gender, true);
else if( plural )
return (gender == Gender.Female ? "les " : "els ") + str;
else
return WithElLaArticle(str, gender, false);
}
private string WithElLaArticle(string str, Gender gender, bool name)
{
if( str.Length != 0 && (IsVowel(str[0]) || str[0] == 'h' || str[0] == 'H') )
{
if( name )
return (gender == Gender.Female ? "l'" : "n'") + str;
else
return "l'" + str;
}
else
return (gender == Gender.Female ? "la " : "el ") + str;
}
public override string OrdinalNumber(int number, Gender gender = Gender.None)
{
if( gender == Gender.Female )
return number + "a";
else if( number == 1 || number == 3 )
return number + "r";
else if( number == 2 )
return number + "n";
else if( number == 4 )
return number + "t";
else
return number + "è";
}
public bool IsVowel(char ch)
{
return "ieɛaoɔuəuàêèéòóüúIEƐAOƆUƏUÀÊÈÉÒÓÜÚ".IndexOf(ch) >= 0;
}
}
Danish
Code Select
public class LanguageWorker_Danish : LanguageWorker
{
public override string WithIndefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
if( str.NullOrEmpty() )
return str;
//Names don't get articles
if( name )
return str;
if( gender == Gender.Male || gender == Gender.Female )
return "en " + str;
else
return "et " + str;
}
public override string WithDefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
if( str.NullOrEmpty() )
return str;
//Names don't get articles
if( name )
return str;
char last = str[str.Length - 1];
if( gender == Gender.Male || gender == Gender.Female )
{
if( last == 'e' )
return str + 'n';
else
return str + "en";
}
else
{
if( last == 'e' )
return str + 't';
else
return str + "et";
}
}
}
Dutch
Code Select
public class LanguageWorker_Dutch : LanguageWorker
{
public override string WithIndefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
//Names don't get articles
if( name )
return str;
if( plural )
return str;
else
return "een " + str;
}
public override string WithDefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
//Names don't get articles
if( name )
return str;
if( plural )
return "de " + str;
else
{
if( gender == Gender.Male || gender == Gender.Female )
return "de " + str;
else
return "het " + str;
}
}
}
English
Code Select
public class LanguageWorker_English : LanguageWorker
{
public override string WithIndefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
if( str.NullOrEmpty() )
return "";
//Names don't get articles
if( name )
return str;
if( plural )
return str;
return "a " + str;
}
public override string WithDefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
if( str.NullOrEmpty() )
return "";
//Names don't get articles
if( name )
return str;
return "the " + str;
}
public override string PostProcessed( string str )
{
str = base.PostProcessed(str);
//Correct a/an cases at the start of the string
if( str.StartsWith("a ", StringComparison.OrdinalIgnoreCase) && str.Length >= 3 )
{
bool hour = str.Substring(2) == "hour";
if( hour || str[2] == 'a' || str[2] == 'e' || str[2] == 'i' || str[2] == 'o' || str[2] == 'u' )
str = str.Insert(1, "n");
}
//Correct a/an cases in the middle of the string
str = str.Replace(" a a", " an a");
str = str.Replace(" a e", " an e");
str = str.Replace(" a i", " an i");
str = str.Replace(" a o", " an o");
str = str.Replace(" a u", " an u");
str = str.Replace(" a hour", " an hour");
str = str.Replace(" A a", " An a");
str = str.Replace(" A e", " An e");
str = str.Replace(" A i", " An i");
str = str.Replace(" A o", " An o");
str = str.Replace(" A u", " An u");
str = str.Replace(" A hour", " An hour");
return str;
}
public override string ToTitleCase(string str)
{
str = base.ToTitleCase(str);
str = str.Replace(" No. ", " no. ");
str = str.Replace(" The ", " the ");
str = str.Replace(" A ", " a ");
str = str.Replace(" For ", " for ");
str = str.Replace(" In ", " in ");
str = str.Replace(" With ", " with ");
return str;
}
public override string OrdinalNumber(int number, Gender gender = Gender.None)
{
int lastDigit = number % 10;
int secondLastDigit = (number / 10) % 10;
if( secondLastDigit != 1 )
{
if( lastDigit == 1 )
return number + "st";
if( lastDigit == 2 )
return number + "nd";
if( lastDigit == 3 )
return number + "rd";
}
return number + "th";
}
public override string Pluralize(string str, Gender gender, int count = -1)
{
if( str.NullOrEmpty() )
return str;
// it's ok if these rules are not perfect,
// we can usually specify the pluralized label in the Def if needed
char last = str[str.Length - 1];
char oneBeforeLast = str.Length == 1 ? '\0' : str[str.Length - 2];
bool oneBeforeLastIsVowel = char.IsLetter(oneBeforeLast) && "oaieuyOAIEUY".IndexOf(oneBeforeLast) >= 0;
bool oneBeforeLastIsConsonant = char.IsLetter(oneBeforeLast) && !oneBeforeLastIsVowel;
if( last == 'y' && oneBeforeLastIsConsonant )
return str.Substring(0, str.Length - 1) + "ies";
else
return str + "s";
}
}
French
Code Select
public class LanguageWorker_French : LanguageWorker
{
public override string WithIndefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
//Names don't get articles
if( name )
return str;
if( plural )
return "des " + str;
return (gender == Gender.Female ? "une " : "un ") + str;
}
public override string WithDefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
if( str.NullOrEmpty() )
return str;
//Names don't get articles
if( name )
return str;
if( plural )
return "les " + str;
char first = str[0];
if( IsVowel(first) )
return "l'" + str;
return (gender == Gender.Female ? "la " : "le ") + str;
}
public override string OrdinalNumber(int number, Gender gender = Gender.None)
{
return number == 1 ? number + "er" : number + "e";
}
public override string Pluralize(string str, Gender gender, int count = -1)
{
if( str.NullOrEmpty() )
return str;
if( str[str.Length - 1] == 's' || str[str.Length - 1] == 'x' )
return str;
else
return str + "s";
}
public override string PostProcessed(string str)
{
return PostProcessedInt(base.PostProcessed(str));
}
public override string PostProcessedKeyedTranslation(string translation)
{
return PostProcessedInt(base.PostProcessedKeyedTranslation(translation));
}
public bool IsVowel(char ch)
{
return "iuyeøoɛœəɔaãɛ̃œ̃ɔ̃IUYEØOƐŒƏƆAÃƐ̃Œ̃Ɔ̃".IndexOf(ch) >= 0;
}
private string PostProcessedInt(string str)
{
return str.Replace(" de le ", " du ")
.Replace(" de les ", " des ")
.Replace(" de des ", " des ");
}
}
German
Code Select
public class LanguageWorker_German : LanguageWorker
{
public override string WithIndefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
//Names don't get articles
if( name )
return str;
switch( gender )
{
case Gender.Male: return "ein " + str;
case Gender.Female: return "eine " + str;
case Gender.None: return "ein " + str;
default: return str;
}
}
public override string WithDefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
//Names don't get articles
if( name )
return str;
switch( gender )
{
case Gender.Male: return "der " + str;
case Gender.Female: return "die " + str;
case Gender.None: return "das " + str;
default: return str;
}
}
public override string OrdinalNumber(int number, Gender gender = Gender.None)
{
return number + ".";
}
public override string Pluralize(string str, Gender gender, int count = -1)
{
if( str.NullOrEmpty() )
return str;
char last = str[str.Length - 1];
char oneBeforeLast = str.Length >= 2 ? str[str.Length - 2] : '\0';
switch( gender )
{
case Gender.Male:
if( last == 'r' && oneBeforeLast == 'e' )
return str;
else if( last == 'l' && oneBeforeLast == 'e' )
return str;
else if( last == 'R' && oneBeforeLast == 'E' )
return str;
else if( last == 'L' && oneBeforeLast == 'E' )
return str;
else if( char.IsUpper(last) )
return str + 'E';
else
return str + 'e';
case Gender.Female:
if( last == 'e' )
return str + 'n';
else if( last == 'E' )
return str + 'N';
else if( last == 'n' && oneBeforeLast == 'i' )
return str + "nen";
else if( last == 'N' && oneBeforeLast == 'I' )
return str + "NEN";
else if( char.IsUpper(last) )
return str + "EN";
else
return str + "en";
case Gender.None:
if( last == 'r' && oneBeforeLast == 'e' )
return str;
else if( last == 'l' && oneBeforeLast == 'e' )
return str;
else if( last == 'n' && oneBeforeLast == 'e' )
return str;
else if( last == 'R' && oneBeforeLast == 'E' )
return str;
else if( last == 'L' && oneBeforeLast == 'E' )
return str;
else if( last == 'N' && oneBeforeLast == 'E' )
return str;
else if( char.IsUpper(last) )
return str + "EN";
else
return str + "en";
default:
return str;
}
}
}
Hungarian
Code Select
public class LanguageWorker_Hungarian : LanguageWorker
{
public override string WithIndefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
//Names don't get articles
if( name )
return str;
return "egy " + str;
}
public override string WithDefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
if( str.NullOrEmpty() )
return str;
//Names don't get articles
if( name )
return str;
char first = str[0];
if( IsVowel(first) )
return "az " + str;
else
return "a " + str;
}
public bool IsVowel(char ch)
{
return "eéöőüűiíaáoóuúEÉÖŐÜŰIÍAÁOÓUÚ".IndexOf(ch) >= 0;
}
}
Italian
Code Select
public class LanguageWorker_Italian : LanguageWorker
{
public override string WithIndefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
//Names don't get articles
if( name )
return str;
char first = str[0];
char second = str.Length >= 2 ? str[1] : '\0';
if( gender == Gender.Female )
{
if( IsVowel(first) )
return "un'" + str;
else
return "una " + str;
}
else
{
char firstLow = char.ToLower(first);
char secondLow = char.ToLower(second);
if( (first == 's' || first == 'S') && !IsVowel(second) )
return "uno " + str;
else if( (firstLow == 'p' && secondLow == 's') || (firstLow == 'p' && secondLow == 'n') || firstLow == 'z' || firstLow == 'x' || firstLow == 'y' || (firstLow == 'g' && secondLow == 'n') )
return "uno " + str;
else
return "un " + str;
}
}
public override string WithDefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
if( str.NullOrEmpty() )
return str;
//Names don't get articles
if( name )
return str;
char first = str[0];
char second = str.Length >= 2 ? str[1] : '\0';
if( gender == Gender.Female )
{
if( IsVowel(first) )
return "l'" + str;
else
return "la " + str;
}
else
{
if( first == 'z' || first == 'Z' )
return "lo " + str;
else if( (first == 's' || first == 'S') && !IsVowel(second) )
return "lo " + str;
else if( IsVowel(first) )
return "l'" + str;
else
return "il " + str;
}
}
public bool IsVowel(char ch)
{
return "aeiouAEIOU".IndexOf(ch) >= 0;
}
public override string OrdinalNumber(int number, Gender gender = Gender.None)
{
return number + "°";
}
public override string Pluralize(string str, Gender gender, int count = -1)
{
if( str.NullOrEmpty() )
return str;
char last = str[str.Length - 1];
if( !IsVowel(last) )
return str;
else if( gender == Gender.Female )
return str.Substring(0, str.Length - 1) + 'e';
else
return str.Substring(0, str.Length - 1) + 'i';
}
}
Korean
Code Select
public class LanguageWorker_Korean : LanguageWorker
{
public override string PostProcessed(string str)
{
str = base.PostProcessed(str);
str = ReplaceJosa(str);
return str;
}
public override string PostProcessedKeyedTranslation(string translation)
{
translation = base.PostProcessedKeyedTranslation(translation);
translation = ReplaceJosa(translation);
return translation;
}
//--------------------- ReplaceJosa -----------------------
//Types
private struct JosaPair
{
public readonly string josa1, josa2;
public JosaPair(string josa1, string josa2)
{
this.josa1 = josa1;
this.josa2 = josa2;
}
}
//Working vars
private static StringBuilder tmpStringBuilder = new StringBuilder();
//Constants
private static readonly Regex JosaPattern = new Regex(@"\(이\)가|\(와\)과|\(을\)를|\(은\)는|\(아\)야|\(이\)여|\(으\)로|\(이\)라");
private static readonly Dictionary<string, JosaPair> JosaPatternPaired = new Dictionary<string, JosaPair>
{
{"(이)가", new JosaPair("이", "가")},
{"(와)과", new JosaPair("과", "와")},
{"(을)를", new JosaPair("을", "를")},
{"(은)는", new JosaPair("은", "는")},
{"(아)야", new JosaPair("아", "야")},
{"(이)여", new JosaPair("이여", "여")},
{"(으)로", new JosaPair("으로", "로")},
{"(이)라", new JosaPair("이라", "라")}
};
private static readonly List<char> AlphabetEndPattern = new List<char> { 'b', 'c', 'k', 'l', 'm', 'n', 'p', 'q', 't' };
public string ReplaceJosa(string src)
{
tmpStringBuilder.Length = 0;
var josaMatches = JosaPattern.Matches(src);
var lastHeadIndex = 0;
for( int i = 0; i < josaMatches.Count; i++ )
{
var josaMatch = josaMatches[i];
var matchingPair = JosaPatternPaired[josaMatch.Value];
tmpStringBuilder.Append(src, lastHeadIndex, josaMatch.Index - lastHeadIndex);
if( josaMatch.Index > 0 )
{
var prevChar = src[josaMatch.Index - 1];
if ((josaMatch.Value != "(으)로" && HasJong(prevChar)) ||
(josaMatch.Value == "(으)로" && HasJongExceptRieul(prevChar)))
{
tmpStringBuilder.Append(matchingPair.josa1);
}
else
tmpStringBuilder.Append(matchingPair.josa2);
}
else
tmpStringBuilder.Append(matchingPair.josa1);
lastHeadIndex = josaMatch.Index + josaMatch.Length;
}
tmpStringBuilder.Append(src, lastHeadIndex, src.Length - lastHeadIndex);
return tmpStringBuilder.ToString();
}
private bool HasJong(char inChar)
{
if( !IsKorean(inChar) )
return AlphabetEndPattern.Contains(inChar);
var localCode = inChar - 0xAC00; // 가~ 이후 로컬 코드
var jongCode = localCode % 28;
return jongCode > 0;
}
private bool HasJongExceptRieul(char inChar)
{
if( !IsKorean(inChar) )
return false;
var localCode = inChar - 0xAC00;
var jongCode = localCode % 28;
return jongCode != 8 && jongCode != 0;
}
private bool IsKorean(char inChar)
{
return inChar >= 0xAC00 && inChar <= 0xD7A3;
}
}