diff options
Diffstat (limited to 'src/lang.c')
-rw-r--r-- | src/lang.c | 60 |
1 files changed, 58 insertions, 2 deletions
@@ -19,12 +19,32 @@ int cmp_MsgStr_(const void *e1, const void *e2) { | |||
19 | 19 | ||
20 | /*----------------------------------------------------------------------------------------------*/ | 20 | /*----------------------------------------------------------------------------------------------*/ |
21 | 21 | ||
22 | enum iPluralType { | ||
23 | none_PluralType, | ||
24 | notEqualToOne_PluralType, | ||
25 | slavic_PluralType, | ||
26 | }; | ||
27 | |||
22 | struct Impl_Lang { | 28 | struct Impl_Lang { |
23 | iSortedArray *messages; | 29 | iSortedArray *messages; |
30 | enum iPluralType pluralType; | ||
24 | }; | 31 | }; |
25 | 32 | ||
26 | static iLang lang_; | 33 | static iLang lang_; |
27 | 34 | ||
35 | static size_t pluralIndex_Lang_(const iLang *d, int n) { | ||
36 | switch (d->pluralType) { | ||
37 | case notEqualToOne_PluralType: | ||
38 | return n != 1; | ||
39 | case slavic_PluralType: | ||
40 | return n % 10 == 1 && n % 100 != 11 ? 0 | ||
41 | : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 | ||
42 | : 2; | ||
43 | default: | ||
44 | return 0; | ||
45 | } | ||
46 | } | ||
47 | |||
28 | static void clear_Lang_(iLang *d) { | 48 | static void clear_Lang_(iLang *d) { |
29 | clear_SortedArray(d->messages); | 49 | clear_SortedArray(d->messages); |
30 | } | 50 | } |
@@ -36,6 +56,15 @@ static void load_Lang_(iLang *d, const char *id) { | |||
36 | : equal_CStr(id, "ru") ? &blobRu_Embedded | 56 | : equal_CStr(id, "ru") ? &blobRu_Embedded |
37 | : equal_CStr(id, "de") ? &blobDe_Embedded | 57 | : equal_CStr(id, "de") ? &blobDe_Embedded |
38 | : &blobEn_Embedded; | 58 | : &blobEn_Embedded; |
59 | if (data == &blobRu_Embedded) { | ||
60 | d->pluralType = slavic_PluralType; | ||
61 | } | ||
62 | // else if (data == &blobZhHans_Embedded) { | ||
63 | // d->pluralType = none_PluralType; | ||
64 | // } | ||
65 | else { | ||
66 | d->pluralType = notEqualToOne_PluralType; | ||
67 | } | ||
39 | iMsgStr msg; | 68 | iMsgStr msg; |
40 | for (const char *ptr = constBegin_Block(data); ptr != constEnd_Block(data); ptr++) { | 69 | for (const char *ptr = constBegin_Block(data); ptr != constEnd_Block(data); ptr++) { |
41 | msg.id.start = ptr; | 70 | msg.id.start = ptr; |
@@ -45,6 +74,7 @@ static void load_Lang_(iLang *d, const char *id) { | |||
45 | while (*++ptr) {} | 74 | while (*++ptr) {} |
46 | msg.str.end = ptr; | 75 | msg.str.end = ptr; |
47 | /* Allocate the string. The data has already been sorted. */ | 76 | /* Allocate the string. The data has already been sorted. */ |
77 | printf("ID:%s\n", msg.id.start); | ||
48 | pushBack_Array(&d->messages->values, &msg); | 78 | pushBack_Array(&d->messages->values, &msg); |
49 | } | 79 | } |
50 | } | 80 | } |
@@ -87,12 +117,30 @@ iRangecc range_Lang(iRangecc msgId) { | |||
87 | return str; | 117 | return str; |
88 | } | 118 | } |
89 | 119 | ||
120 | const iString *string_Lang(const char *msgId) { | ||
121 | return collectNewRange_String(range_Lang(range_CStr(msgId))); | ||
122 | } | ||
123 | |||
90 | const char *cstr_Lang(const char *msgId) { | 124 | const char *cstr_Lang(const char *msgId) { |
91 | return range_Lang(range_CStr(msgId)).start; /* guaranteed to be NULL-terminated */ | 125 | return range_Lang(range_CStr(msgId)).start; /* guaranteed to be NULL-terminated */ |
92 | } | 126 | } |
93 | 127 | ||
94 | const iString *string_Lang(const char *msgId) { | 128 | static char *pluralId_Lang_(const iLang *d, const char *msgId, int count) { |
95 | return collectNewRange_String(range_Lang(range_CStr(msgId))); | 129 | const size_t len = strlen(msgId); |
130 | char *pluralId = strdup(msgId); | ||
131 | pluralId[len - 1] = '0' + pluralIndex_Lang_(d, count); | ||
132 | return pluralId; | ||
133 | } | ||
134 | |||
135 | const char *cstrCount_Lang(const char *msgId, int count) { | ||
136 | iAssert(endsWith_Rangecc(range_CStr(msgId), ".n")); /* by convention */ | ||
137 | char *pluralId = pluralId_Lang_(&lang_, msgId, count); | ||
138 | const char *str = cstr_Lang(pluralId); | ||
139 | if (str == pluralId) { | ||
140 | str = msgId; /* not found */ | ||
141 | } | ||
142 | free(pluralId); | ||
143 | return str; | ||
96 | } | 144 | } |
97 | 145 | ||
98 | void translate_Lang(iString *textWithIds) { | 146 | void translate_Lang(iString *textWithIds) { |
@@ -129,3 +177,11 @@ const char *translateCStr_Lang(const char *textWithIds) { | |||
129 | translate_Lang(text); | 177 | translate_Lang(text); |
130 | return cstr_String(text); | 178 | return cstr_String(text); |
131 | } | 179 | } |
180 | |||
181 | const char *formatCStr_Lang(const char *formatMsgId, int count) { | ||
182 | return format_CStr(cstrCount_Lang(formatMsgId, count), count); | ||
183 | } | ||
184 | |||
185 | const char *formatCStrs_Lang(const char *formatMsgId, size_t count) { | ||
186 | return format_CStr(cstrCount_Lang(formatMsgId, (int) count), count); | ||
187 | } | ||