diff options
author | ludde <ludde@openttd.org> | 2005-07-16 17:12:32 +0000 |
---|---|---|
committer | ludde <ludde@openttd.org> | 2005-07-16 17:12:32 +0000 |
commit | 61558dcb3d19e10bb14c1fa360219fb26584e45c (patch) | |
tree | 044012c639fb626159d67ea02a9ef0e3ccff68b6 /strings.c | |
parent | 11d9f5011562541eff281e4529f77dfea6bf18ee (diff) | |
download | openttd-61558dcb3d19e10bb14c1fa360219fb26584e45c.tar.xz |
(svn r2592) Feature: [strgen] New way to specify plural forms.
- {NUM} {PLURAL 0 car cars}: Prints either car or cars depending on if the argument 0 is plural.
Also supports languages with weird plural forms such as Polish.
The plural format needs to be specified in the beginning of the langfile, like "##plural 7" for Polish.
Diffstat (limited to 'strings.c')
-rw-r--r-- | strings.c | 93 |
1 files changed, 91 insertions, 2 deletions
@@ -27,6 +27,8 @@ typedef struct LanguagePack { char own_name[32]; // the localized name of this language char isocode[16]; // the ISO code for the language (not country code) uint16 offsets[32]; // the offsets + byte plural_form; // how to compute plural forms + byte pad[3]; // pad header to be a multiple of 4 char data[VARARRAY_SIZE]; } LanguagePack; @@ -418,6 +420,89 @@ static char *FormatGenericCurrency(char *buff, const CurrencySpec *spec, int64 n return buff; } +static int DeterminePluralForm(int32 n) +{ + // The absolute value determines plurality + if (n < 0) n = -n; + + switch(_langpack->plural_form) { + // Two forms, singular used for one only + // Used in: + // Danish, Dutch, English, German, Norwegian, Swedish, Estonian, Finnish, + // Greek, Hebrew, Italian, Portuguese, Spanish, Esperanto + case 0: + default: + return n != 1; + + // Only one form + // Used in: + // Hungarian, Japanese, Korean, Turkish + case 1: + return 0; + + // Two forms, singular used for zero and one + // Used in: + // French, Brazilian Portuguese + case 2: + return n > 1; + + // Three forms, special case for zero + // Used in: + // Latvian + case 3: + return n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2; + + // Three forms, special case for one and two + // Used in: + // Gaelige (Irish) + case 4: + return n==1 ? 0 : n==2 ? 1 : 2; + + // Three forms, special case for numbers ending in 1[2-9] + // Used in: + // Lithuanian + case 5: + return n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2; + + // Three forms, special cases for numbers ending in 1 and 2, 3, 4, except those ending in 1[1-4] + // Used in: + // Croatian, Czech, Russian, Slovak, Ukrainian + case 6: + return n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; + + // Three forms, special case for one and some numbers ending in 2, 3, or 4 + // Used in: + // Polish + case 7: + return n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; + + // Four forms, special case for one and all numbers ending in 02, 03, or 04 + // Used in: + // Slovenian + case 8: + return n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3; + } +} + +static const char *ParseStringChoice(const char *b, uint form, char *dst, int *dstlen) +{ + //<NUM> {Length of each string} {each string} + uint n = (byte)*b++; + uint pos,i, mylen=0,mypos=0; + for(i=pos=0; i!=n; i++) { + uint len = (byte)*b++; + if (i == form) { + mypos = pos; + mylen = len; + } + pos += len; + } + *dstlen = mylen; + memcpy(dst, b + mypos, mylen); + return b + pos; +} + + static char *FormatString(char *buff, const char *str, const int32 *argv) { byte b; @@ -440,9 +525,13 @@ static char *FormatString(char *buff, const char *str, const int32 *argv) case 0x7C: // Move argument pointer argv = argv_orig + (byte)*str++; break; - case 0x7D: - assert(0); + case 0x7D: { // {PLURAL} + int32 v = argv_orig[(byte)*str++]; // contains the number that determines plural + int len; + str = ParseStringChoice(str, DeterminePluralForm(v), buff, &len); + buff += len; break; + } case 0x7E: // {NUMU16}, {INT32} buff = FormatNoCommaNumber(buff, GetInt32(&argv)); break; |