Ludeon Forums

Ludeon Forums

  • November 18, 2018, 11:42:59 PM
  • Welcome, Guest
Please login or register.

Login with username, password and session length
Advanced search  
Pages: [1] 2

Author Topic: Request: Help check the language workers for accuracy  (Read 2809 times)

ison

  • Developer
  • Planetologist
  • *****
  • Posts: 2120
    • View Profile
Request: Help check the language workers for accuracy
« on: September 05, 2018, 07:45:23 AM »

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
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;
}
}
« Last Edit: September 07, 2018, 11:09:08 AM by ison »
Logged

ison

  • Developer
  • Planetologist
  • *****
  • Posts: 2120
    • View Profile
Re: Translators! Please check the language workers
« Reply #1 on: September 05, 2018, 07:45:39 AM »

Norwegian
Code: [Select]
public class LanguageWorker_Norwegian : 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( 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";
}
}
}

Portuguese
Code: [Select]
public class LanguageWorker_Portuguese : 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 (gender == Gender.Female ? "umas " : "uns ") + str;
else
return (gender == Gender.Female ? "uma " : "um ") + 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 (gender == Gender.Female ? "as " : "os ") + str;
else
return (gender == Gender.Female ? "a " : "o ") + str;
}
}

Romanian
Code: [Select]
public class LanguageWorker_Romanian : 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 gender == Gender.Male ? str + 'i' : str + 'e';
else
return (gender == Gender.Female ? "a " : "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 last = str[str.Length - 1];

if( plural )
return gender == Gender.Male ? str + 'i' : str + 'e';
else
{
if( !IsVowel(last) )
return str + "ul";
else if( gender == Gender.Male )
return str + "le";
else
return str + 'a';
}
}

public bool IsVowel(char ch)
{
return "aeiouâîAEIOUÂÎ".IndexOf(ch) >= 0;
}
}

Russian
Code: [Select]
namespace Verse
{

public class LanguageWorker_Russian : LanguageWorker
{
    public override string PostProcessed(string str)
    {
        str = base.PostProcessed(str)
            .ProcessTimeSpan()
            .ProcessDate();

        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( IsConsonant(last) )
return str + 'ы';
else if( last == 'й' )
return str.Substring(0, str.Length - 1) + 'и';
else if( last == 'ь' )
return str.Substring(0, str.Length - 1) + 'и';
else if( last == 'Й' )
return str.Substring(0, str.Length - 1) + 'И';
else if( last == 'Ь' )
return str.Substring(0, str.Length - 1) + 'И';
break;

case Gender.Female:
if( last == 'я' )
return str.Substring(0, str.Length - 1) + 'и';
else if( last == 'ь' )
return str.Substring(0, str.Length - 1) + 'и';
else if( last == 'Я' )
return str.Substring(0, str.Length - 1) + 'И';
else if( last == 'Ь' )
return str.Substring(0, str.Length - 1) + 'И';
else if( last == 'a' || last == 'A' )
{
char oneBeforeLastUp = char.ToUpper(oneBeforeLast);
if( "ГКХЖЧШЩ".IndexOf(oneBeforeLastUp) >= 0 )
{
if( last == 'a' )
return str.Substring(0, str.Length - 1) + 'и';
else
return str.Substring(0, str.Length - 1) + 'И';
}
else
{
if( last == 'a' )
return str.Substring(0, str.Length - 1) + 'ы';
else
return str.Substring(0, str.Length - 1) + 'Ы';
}
}
break;

case Gender.None:
if( last == 'o' )
return str.Substring(0, str.Length - 1) + 'a';
else if( last == 'O' )
return str.Substring(0, str.Length - 1) + 'A';
else if( last == 'e' || last == 'E' )
{
char oneBeforeLastUp = char.ToUpper(oneBeforeLast);
if( "ГКХЖЧШЩЦ".IndexOf(oneBeforeLastUp) >= 0 )
{
if( last == 'e' )
return str.Substring(0, str.Length - 1) + 'a';
else if( last == 'E' )
return str.Substring(0, str.Length - 1) + 'A';
}
else
{
if( last == 'e' )
return str.Substring(0, str.Length - 1) + 'я';
else if( last == 'E' )
return str.Substring(0, str.Length - 1) + 'Я';
}
}
break;
}

return str;
}

public bool IsConsonant(char ch)
{
return "бвгджзклмнпрстфхцчшщБВГДЖЗКЛМНПРСТФХЦЧШЩ".IndexOf(ch) >= 0;
}
}

}

namespace Verse.LanguageWorkerInternals_Russian
{

internal static class StringReplaceExt
{
public static string ProcessTimeSpan(this string str)
{
return str
.ReplaceAtStartSpaceOrNewline("1 лет", "1 год")
.ReplaceAtStartSpaceOrNewline("1 кварталов", "1 квартал")
.ReplaceAtStartSpaceOrNewline("1 дней", "1 день")
.ReplaceAtStartSpaceOrNewline("1 часов", "1 час")
.ReplaceRegex("([02-9])1 лет", "${1}1 год")
.ReplaceRegex("([02-9])1 кварталов", "${1}1 квартал")
.ReplaceRegex("([02-9])1 дней", "${1}1 день")
.ReplaceRegex("([02-9])1 часов", "${1}1 час")

.ReplaceAtStartSpaceOrNewline("2 лет", "2 года")
.ReplaceAtStartSpaceOrNewline("2 кварталов", "2 квартала")
.ReplaceAtStartSpaceOrNewline("2 дней", "2 дня")
.ReplaceAtStartSpaceOrNewline("2 часов", "2 часа")
.ReplaceRegex("([02-9])2 лет", "${1}2 года")
.ReplaceRegex("([02-9])2 кварталов", "${1}2 квартала")
.ReplaceRegex("([02-9])2 дней", "${1}2 дня")
.ReplaceRegex("([02-9])2 часов", "${1}2 часа")

.ReplaceAtStartSpaceOrNewline("3 лет", "3 года")
.ReplaceAtStartSpaceOrNewline("3 кварталов", "3 квартала")
.ReplaceAtStartSpaceOrNewline("3 дней", "3 дня")
.ReplaceAtStartSpaceOrNewline("3 часов", "3 часа")
.ReplaceRegex("([02-9])3 лет", "${1}3 года")
.ReplaceRegex("([02-9])3 кварталов", "${1}3 квартала")
.ReplaceRegex("([02-9])3 дней", "${1}3 дня")
.ReplaceRegex("([02-9])3 часов", "${1}3 часа")

.ReplaceAtStartSpaceOrNewline("4 лет", "4 года")
.ReplaceAtStartSpaceOrNewline("4 кварталов", "4 квартала")
.ReplaceAtStartSpaceOrNewline("4 дней", "4 дня")
.ReplaceAtStartSpaceOrNewline("4 часов", "4 часа")
.ReplaceRegex("([02-9])4 лет", "${1}4 года")
.ReplaceRegex("([02-9])4 кварталов", "${1}4 квартала")
.ReplaceRegex("([02-9])4 дней", "${1}4 дня")
.ReplaceRegex("([02-9])4 часов", "${1}4 часа");
}

    public static string ProcessDate(this string str)
    {
        return str
            .Replace("-й мартомай", " мартомая")
            .Replace("-й июгуст", " июгуста")
            .Replace("-й сентоноябрь", " сентоноября")
            .Replace("-й декавраль", " декавраля");
    }

    public static string ReplaceAtIndex(this string str, int index, int length, char replacement)
    {
        return str.ReplaceAtIndex(index, length, replacement.ToString());
    }

    public static string ReplaceAtIndex(this string str, int index, int length, string replacement)
    {
        return str.Remove(index, length).Insert(index, replacement);
    }

    public static string ReplaceRegex(this string str, string pattern, string replaceWith)
    {
        return Regex.Replace(str, pattern, replaceWith);
    }

    public static string ReplaceAtStartSpaceOrNewline(this string str, string toReplace, string replaceWith)
    {
        if (!str.Contains(toReplace))
            return str;

        str = str
            .Replace(' ' + toReplace, ' ' + replaceWith)
            .Replace('\n' + toReplace, '\n' + replaceWith);

        if (str.StartsWith(toReplace))
            str = replaceWith + str.Substring(toReplace.Length);

        return str;
    }
}

}

Spanish
Code: [Select]
public class LanguageWorker_Spanish : 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 (gender == Gender.Female ? "una " : "un ") + str;
}

public override string WithDefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
//Names don't get articles
if( name )
return str;

return (gender == Gender.Female ? "la " : "el ") + 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';

if( IsVowel(last) )
{
if( str == "sí" )
return "síes";
else if( last == 'í' || last == 'ú' || last == 'Í' || last == 'Ú' )
return str + "es";
else
return str + 's';
}
else
{
if( (last == 'y' || last == 'Y') && IsVowel(oneBeforeLast) )
return str + "es";
else if( "lrndzjsxLRNDZJSX".IndexOf(last) >= 0 || (last == 'h' && oneBeforeLast == 'c') )
return str + "es";
else
return str + 's';
}
}

public bool IsVowel(char ch)
{
return "aeiouáéíóúAEIOUÁÉÍÓÚ".IndexOf(ch) >= 0;
}
}

Swedish
Code: [Select]
public class LanguageWorker_Swedish : 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( gender == Gender.Male || gender == Gender.Female )
return "en " + str;
else
return "ett " + 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( IsVowel(last) )
return str + 'n';
else
return str + "en";
}
else
{
if( IsVowel(last) )
return str + 't';
else
return str + "et";
}
}

public bool IsVowel(char ch)
{
return "aeiouyåäöAEIOUYÅÄÖ".IndexOf(ch) >= 0;
}
}

Turkish
Code: [Select]
public class LanguageWorker_Turkish : 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 str + " bir";
}

public override string WithDefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
return str;
}
}
« Last Edit: September 07, 2018, 10:27:22 AM by ison »
Logged

b606

  • Drifter
  • **
  • Posts: 24
  • Refugee
    • View Profile
Re: Request: Help check the language workers for accuracy
« Reply #2 on: September 06, 2018, 11:23:45 AM »

Thanks ison !
For LanguageWorker_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)
{
//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)
{
return number == 1 ? number + "er" : number + "ème";
                // for gender female, should be 1ère instead of 1er
}

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";
}
}

PostProcessing:
I think that there should be also additional "PostProcessed" code to replace " de le " by " du ", and " de les " by " des ", for the inclusion of the definite article in sentences with " de ", such as "the head of the muffalo" -> "la tête de le muffalo" (incorrect)-> "la tête du muffalo" (correct).

For gender female " de la " and definite with vowel " de l'{vowel} " are correct.

For indefinite article and more generally any str starting with a vowel, " de {vowel}" becomes "d'{vowel}". Ex. "the head of a muffalo" -> "la tête de un muffalo" -> "la tête d'un muffalo"

Last, " de des " -> "des"
« Last Edit: September 06, 2018, 11:47:43 AM by b606 »
Logged

mecatxis

  • Drifter
  • **
  • Posts: 35
  • Refugee
    • View Profile
Re: Request: Help check the language workers for accuracy
« Reply #3 on: September 06, 2018, 03:33:21 PM »

Thanks Ison!

I am reworking for Catalan. I am not a programmer, so please, excuse my mistakes and misunderstandings.
The article should be contracted when started with vowel or h (el Carles, l'Òscar, la Rosa, l'Anna). There is some exceptions if the first syllable is tonic an others, but i understand it will be very difficult to tract. so:

Code: [Select]
public override string WithIndefiniteArticle(string str, Gender gender, bool plural = false, bool name = false)
{
if( name )
char first = str[0];
if (IsVowelorh(first)
{
return (gender == Gender.Female ? "l/'" : "n/'") + str;
}
else
{
return (gender == Gender.Female ? "la " : "el ") + str;
}
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 )
char first = str[0];
if (IsVowelorh(first)
{
return (gender == Gender.Female ? "l/'" : "n/'") + str;
}
else
{
return (gender == Gender.Female ? "la " : "el ") + str;
}
else if( plural )
return (gender == Gender.Female ? "les " : "els ") + str;
else
return (gender == Gender.Female ? "la " : "el ") + str;
}
public bool IsVowelorh(char ch)
{
return "aeiouàèéíòóúïüAEIOUÀÈÉÍÒÓÚÏÜ".IndexOf(ch) >= 0;
}

Ordinals can change depending on number and the gender of the thing counted. I have seen them treated on some workers. I don't know if is possible something like this:

Code: [Select]
public override string OrdinalNumber(int number, Gender gender)
{
if ( gender == Gender.Female)
{
return number + "a";
}
else
{
if( int == 1 or int == 3)
return number + "r";
else if (int == 2)
return number + "n";
else if (int == 4)
return number + "t";
else
return number + "è";
}
}


Thanks again! Very good job!
« Last Edit: September 07, 2018, 02:27:14 AM by mecatxis »
Logged

ison

  • Developer
  • Planetologist
  • *****
  • Posts: 2120
    • View Profile
Re: Request: Help check the language workers for accuracy
« Reply #4 on: September 07, 2018, 10:27:31 AM »

Great, thank you for your feedback.

I've modified both French and Catalan language workers. You can see the updated code in my first post.

And please don't worry if the code is difficult to read. It's perfectly fine to just describe the problem in English or use pseudo-code.

In Catalan, I'm not sure if I got the 'l 'n right. Currently it's like this:
If it's indefinite, it's a name, and the first character is either a vowel or h: use either 'l or 'n depending on the gender.
If it's definite, it's a name, and the first character is either a vowel or h: use either 'l or 'n depending on the gender.
If it's definite, it's not a name, and the first character is either a vowel or h: always use 'l
Logged

mecatxis

  • Drifter
  • **
  • Posts: 35
  • Refugee
    • View Profile
Re: Request: Help check the language workers for accuracy
« Reply #5 on: September 07, 2018, 02:20:42 PM »

Quote
If it's indefinite, it's a name, and the first character is either a vowel or h: use either 'l or 'n depending on the gender.
If it's definite, it's a name, and the first character is either a vowel or h: use either 'l or 'n depending on the gender.
If it's definite, it's not a name, and the first character is either a vowel or h: always use 'l

it is not 'l. It is l', as in l'Oriol (man) or l'Hortènsia (woman)

I can work with this simplification of the rule , more or less.

Here is the complete rule https://www.cursdecatala.com/en/catalan-apostrophe/


Logged

mecatxis

  • Drifter
  • **
  • Posts: 35
  • Refugee
    • View Profile
Re: Request: Help check the language workers for accuracy
« Reply #6 on: September 08, 2018, 06:27:47 AM »

Pluralize in Catalan.
You can find the rule here: http://mylanguages.org/catalan_plural.php
Usualy only needs to add -s

Finishing with -a changes to -es, except for ça goes to ces, -ca goes to -ques, -qua goes to -qües, -ja goes to -ges, -ga goes to -gues.

Finishing with -s. Basicaly:
- finishing with -às goes to -assos
- finishing with -és goes to -essos
- finishing with -es goes to -esos
- finishing with -és goes to -issos
- finishing with -ós, òs or monosyllables (hard to know automatically) ending with -os goes to -ossos
- finishing with -ús goes to -ussos

The hard thing will be
Quote
words ending in a stressed vowel form the plural by adding (-ns)
. Does any other language solved this problem? Any idea how to detect a stressed syllabe?

- UPDATED
I misunderstood the problem.It is as easy as words ending in "àéèíòóú" pluralize adding -ns. Thanks!

« Last Edit: September 12, 2018, 02:10:15 AM by mecatxis »
Logged

b606

  • Drifter
  • **
  • Posts: 24
  • Refugee
    • View Profile
Re: Request: Help check the language workers for accuracy
« Reply #7 on: September 08, 2018, 07:34:45 AM »

For LanguageWorker_French, after further testing and checks

1) The letters "yY" should be removed from the vowels list since definite article for these is not "l'". Ex : "the yacht" ->  "le yacht" not "l'yacht".

2) Most of words starting with "h" (case of so called 'h muet') get " l' " but there are exceptions. Ex: "the man" -> "l'homme", "l'hortensia" but "la hotte". Unless someone could define the grammatical rule for that, I would treat this as a general case and process the exception differently. The idea is that in RimWorld, the words with that exception are really rare.

3) Additional PostProcessed :
a) "if [*_pronoun]" -> "if he" -> "si il" -> "s'il" ("if she" -> "si elle" is correct)
b) " de {vowel}..." -> " d'{vowel} " : as a pseudocode, would be
    - find " de " in str
    - check if next char c IsVowel(c), if true replace only that " de " with " d'"

Code: [Select]
public bool IsVowel(char ch)
{
return "hiueøoɛœəɔaãɛ̃œ̃ɔ̃IHUEØOƐŒƏƆAÃƐ̃Œ̃Ɔ̃".IndexOf(ch) >= 0;
}


private string PostProcessedInt(string str)
{
return str.Replace(" de le ", " du ")
.Replace(" de les ", " des ")
.Replace(" de des ", " des ")
.Replace(" si il ", " s'il ")
.Replace(" Si il ", " S'il ");
}

Best regards !
Logged

mecatxis

  • Drifter
  • **
  • Posts: 35
  • Refugee
    • View Profile
Re: Request: Help check the language workers for accuracy
« Reply #8 on: September 11, 2018, 05:07:53 AM »

I am trying to implement it, but not guessing how is supposed to work. Checking for "Do you really want to banish {1_label}?":

1 - Esteu segur que voleu fer fora WithDefiniteArticle({1_label})?
Got "Esteu segur que voleu fer fora WithDefiniteArticle(Pree, Herborista)?"

2 - Esteu segur que voleu fer fora (WithDefiniteArticle({1_label}))?
Got "Esteu segur que voleu fer fora (WithDefiniteArticle(Pree, Herborista))?"

3 - Esteu segur que voleu fer fora {WithDefiniteArticle(1_label)}?
Gets "Esteu segur que voleu fer fora ?

Other combinations give similar wrong results. Can anybody help?
Logged

b606

  • Drifter
  • **
  • Posts: 24
  • Refugee
    • View Profile
Re: Request: Help check the language workers for accuracy
« Reply #9 on: September 12, 2018, 06:05:41 AM »

I do not speak this language at all (though same family language.). So, what is wrong with
- "Esteu segur que voleu fer fora {1_label} ?"
or
- "Esteu segur que voleu fer fora {1_nameDef} ?"
Logged

mecatxis

  • Drifter
  • **
  • Posts: 35
  • Refugee
    • View Profile
Re: Request: Help check the language workers for accuracy
« Reply #10 on: September 13, 2018, 03:12:40 AM »

Quote
I do not speak this language at all (though same family language.). So, what is wrong with
- "Esteu segur que voleu fer fora {1_label} ?"
or
- "Esteu segur que voleu fer fora {1_nameDef} ?"

I will try to explain better. I am trying to use "WithDefiniteArticle" in the translation of the sentence "Do you really want to banish {1_label}" (this is how it shows in the original file).

I expected to get "Esteu segur que voleu fer fora el John" or "Esteu segur que voleu fer fora la Mary" depending on the gender of the subject.

I am asking how do i should implement the "WithDefiniteArticle" worker.

Logged

Varisha

  • Drifter
  • **
  • Posts: 68
  • Refugee
    • View Profile
Re: Request: Help check the language workers for accuracy
« Reply #11 on: September 13, 2018, 03:31:08 AM »

Hi,

this is a great feature to get things more flexible. I wonder how to trigger the Pluralize method using the games mechanics to check if the change is ok.
Can you give me short help on this? :)
Logged

mecatxis

  • Drifter
  • **
  • Posts: 35
  • Refugee
    • View Profile
Re: Request: Help check the language workers for accuracy
« Reply #12 on: September 13, 2018, 02:36:09 PM »

Quote
I do not speak this language at all (though same family language.). So, what is wrong with
- "Esteu segur que voleu fer fora {1_label} ?"
or
- "Esteu segur que voleu fer fora {1_nameDef} ?"

I will try to explain better. I am trying to use "WithDefiniteArticle" in the translation of the sentence "Do you really want to banish {1_label}" (this is how it shows in the original file).

I expected to get "Esteu segur que voleu fer fora el John" or "Esteu segur que voleu fer fora la Mary" depending on the gender of the subject.

I am asking how do i should implement the "WithDefiniteArticle" worker.

I finally found the answer:
Code: [Select]
"Esteu segur que voleu fer fora {1_definite}?"
Logged

mecatxis

  • Drifter
  • **
  • Posts: 35
  • Refugee
    • View Profile
Re: Request: Help check the language workers for accuracy
« Reply #13 on: September 17, 2018, 02:27:06 PM »

For {0_objective} could i have
"la" if is female. Otherwise "lo".
?

Thanks
Logged

Angiel

  • Drifter
  • **
  • Posts: 33
  • Refugee
    • View Profile
Re: Translators! Please check the language workers
« Reply #14 on: September 19, 2018, 06:01:44 PM »


Romanian
Code: [Select]
if( plural )
return gender == Gender.Male ? str + 'i' : str + 'e';
else
return (gender == Gender.Female ? "a " : "un ") + str;


So in this part of the code, i think you are trying to determine the gender of the word by the indefinite article of the word.
In romanian the feminine words have the indefinite article "o " in front not "a " like stated in the code.
e. g. o femeie, o mașină, o sfoară etc.

And we don't have only 2 genders sadly :)). we have a third gender which is neutral
The indefinite article in singular form is "un " like masculine words, but the plural is formed like the feminine one.

e.g. un scaun, plural: scaune = scaun + e (feminin plural); (chair)
      un geamantan, plural: geamantane (suitcase, trunk)

and if i understand again the code right, which i am not very sure since the terminology isn't familiar to me :D. you only form or search the plural for feminine with termination "e" and for masculine "i".
in that case there are plural words that end in "i" that are actually feminine,
e.g. o vaca, plural: vaci  ( cow, which is actually in the game)
      o minte, plural: minți (this means mind)

i can't say if there is a rule for this or if there are just some words which make an exception, ironically
e.g. o excepție, plural: excepții which means exception if you haven't guessed already :D.
I think it has to do with the way the word ends because "vace" would sound wrong, and the others seem to end in "e" already so it can't have double "ee" to form the plural.

I could help further but like i said i don't really understand the logic of the code, as in what the conditions are searching for and what should the functions return.

For example this part of the code
what i understand is that here you are trying to give the words the definitive article form of the words.

Code: [Select]
if( !IsVowel(last) )
return str + "ul";
else if( gender == Gender.Male )
return str + "le";
else
return str + 'a';


so my logic of the code would be
1 it puts a condition if the last letter of the word doesn't end in a vowel
2 it should add the termination "ul"
3 if it does end in a vowel it should see if the gender of the word is masculine
4 if masculine should add the termination "le" ;;; termination "le" is the definitive article form for plural words not for masculine, the "ul" termination is for singular form masculine and neutral genders.
5 if not masculine, hence feminine add the termination "a" ;;; which is correct.

well i won't try and say anything further i think i said a lot and if i say more and i am understanding the code wrong then i am doing stuff in vain :).


« Last Edit: September 19, 2018, 06:04:39 PM by Angiel »
Logged
Pages: [1] 2