printer_test.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package locale // import "miniflux.app/v2/internal/locale"
  4. import "testing"
  5. func TestPrintfWithMissingLanguage(t *testing.T) {
  6. defaultCatalog = catalog{}
  7. translation := NewPrinter("invalid").Printf("missing.key")
  8. if translation != "missing.key" {
  9. t.Errorf(`Wrong translation, got %q`, translation)
  10. }
  11. }
  12. func TestPrintfWithMissingKey(t *testing.T) {
  13. defaultCatalog = catalog{
  14. "en_US": translationDict{
  15. singulars: map[string]string{
  16. "k": "v",
  17. },
  18. },
  19. }
  20. translation := NewPrinter("en_US").Printf("missing.key")
  21. if translation != "missing.key" {
  22. t.Errorf(`Wrong translation, got %q`, translation)
  23. }
  24. }
  25. func TestPrintfWithExistingKey(t *testing.T) {
  26. defaultCatalog = catalog{
  27. "en_US": translationDict{
  28. singulars: map[string]string{
  29. "auth.username": "Login",
  30. },
  31. },
  32. }
  33. translation := NewPrinter("en_US").Printf("auth.username")
  34. if translation != "Login" {
  35. t.Errorf(`Wrong translation, got %q`, translation)
  36. }
  37. }
  38. func TestPrintfWithExistingKeyAndPlaceholder(t *testing.T) {
  39. defaultCatalog = catalog{
  40. "en_US": translationDict{
  41. singulars: map[string]string{
  42. "key": "Test: %s",
  43. },
  44. },
  45. "fr_FR": translationDict{
  46. singulars: map[string]string{
  47. "key": "Test : %s",
  48. },
  49. },
  50. }
  51. translation := NewPrinter("fr_FR").Printf("key", "ok")
  52. if translation != "Test : ok" {
  53. t.Errorf(`Wrong translation, got %q`, translation)
  54. }
  55. }
  56. func TestPrintfWithMissingKeyAndPlaceholder(t *testing.T) {
  57. defaultCatalog = catalog{
  58. "en_US": translationDict{
  59. singulars: map[string]string{
  60. "auth.username": "Login",
  61. },
  62. },
  63. "fr_FR": translationDict{
  64. singulars: map[string]string{
  65. "auth.username": "Identifiant",
  66. },
  67. },
  68. }
  69. translation := NewPrinter("fr_FR").Printf("Status: %s", "ok")
  70. if translation != "Status: ok" {
  71. t.Errorf(`Wrong translation, got %q`, translation)
  72. }
  73. }
  74. func TestPrintWithMissingLanguage(t *testing.T) {
  75. defaultCatalog = catalog{}
  76. translation := NewPrinter("invalid").Print("missing.key")
  77. if translation != "missing.key" {
  78. t.Errorf(`Wrong translation, got %q`, translation)
  79. }
  80. }
  81. func TestPrintWithMissingKey(t *testing.T) {
  82. defaultCatalog = catalog{
  83. "en_US": translationDict{
  84. singulars: map[string]string{
  85. "existing.key": "value",
  86. },
  87. },
  88. }
  89. translation := NewPrinter("en_US").Print("missing.key")
  90. if translation != "missing.key" {
  91. t.Errorf(`Wrong translation, got %q`, translation)
  92. }
  93. }
  94. func TestPrintWithExistingKey(t *testing.T) {
  95. defaultCatalog = catalog{
  96. "en_US": translationDict{
  97. singulars: map[string]string{
  98. "auth.username": "Login",
  99. },
  100. },
  101. }
  102. translation := NewPrinter("en_US").Print("auth.username")
  103. if translation != "Login" {
  104. t.Errorf(`Wrong translation, got %q`, translation)
  105. }
  106. }
  107. func TestPrintWithDifferentLanguages(t *testing.T) {
  108. defaultCatalog = catalog{
  109. "en_US": translationDict{
  110. singulars: map[string]string{
  111. "greeting": "Hello",
  112. },
  113. },
  114. "fr_FR": translationDict{
  115. singulars: map[string]string{
  116. "greeting": "Bonjour",
  117. },
  118. },
  119. "es_ES": translationDict{
  120. singulars: map[string]string{
  121. "greeting": "Hola",
  122. },
  123. },
  124. }
  125. tests := []struct {
  126. language string
  127. expected string
  128. }{
  129. {"en_US", "Hello"},
  130. {"fr_FR", "Bonjour"},
  131. {"es_ES", "Hola"},
  132. }
  133. for _, test := range tests {
  134. translation := NewPrinter(test.language).Print("greeting")
  135. if translation != test.expected {
  136. t.Errorf(`Wrong translation for %s, got %q instead of %q`, test.language, translation, test.expected)
  137. }
  138. }
  139. }
  140. func TestPrintWithEmptyKey(t *testing.T) {
  141. defaultCatalog = catalog{
  142. "en_US": translationDict{
  143. singulars: map[string]string{
  144. "": "empty key translation",
  145. },
  146. },
  147. }
  148. translation := NewPrinter("en_US").Print("")
  149. if translation != "empty key translation" {
  150. t.Errorf(`Wrong translation for empty key, got %q`, translation)
  151. }
  152. }
  153. func TestPrintWithEmptyTranslation(t *testing.T) {
  154. defaultCatalog = catalog{
  155. "en_US": translationDict{
  156. singulars: map[string]string{
  157. "empty.value": "",
  158. },
  159. },
  160. }
  161. translation := NewPrinter("en_US").Print("empty.value")
  162. if translation != "" {
  163. t.Errorf(`Wrong translation for empty value, got %q`, translation)
  164. }
  165. }
  166. func TestPluralWithDefaultRule(t *testing.T) {
  167. defaultCatalog = catalog{
  168. "en_US": translationDict{
  169. plurals: map[string][]string{
  170. "number_of_users": {"%d user (%s)", "%d users (%s)"},
  171. },
  172. },
  173. "fr_FR": translationDict{
  174. plurals: map[string][]string{
  175. "number_of_users": {"%d utilisateur (%s)", "%d utilisateurs (%s)"},
  176. },
  177. },
  178. }
  179. printer := NewPrinter("fr_FR")
  180. translation := printer.Plural("number_of_users", 1, 1, "some text")
  181. expected := "1 utilisateur (some text)"
  182. if translation != expected {
  183. t.Errorf(`Wrong translation, got %q instead of %q`, translation, expected)
  184. }
  185. translation = printer.Plural("number_of_users", 2, 2, "some text")
  186. expected = "2 utilisateurs (some text)"
  187. if translation != expected {
  188. t.Errorf(`Wrong translation, got %q instead of %q`, translation, expected)
  189. }
  190. }
  191. func TestPluralWithRussianRule(t *testing.T) {
  192. defaultCatalog = catalog{
  193. "en_US": translationDict{
  194. plurals: map[string][]string{
  195. "time_elapsed.years": {"%d year", "%d years"},
  196. },
  197. },
  198. "ru_RU": translationDict{
  199. plurals: map[string][]string{
  200. "time_elapsed.years": {"%d год назад", "%d года назад", "%d лет назад"},
  201. },
  202. },
  203. }
  204. printer := NewPrinter("ru_RU")
  205. translation := printer.Plural("time_elapsed.years", 1, 1)
  206. expected := "1 год назад"
  207. if translation != expected {
  208. t.Errorf(`Wrong translation, got %q instead of %q`, translation, expected)
  209. }
  210. translation = printer.Plural("time_elapsed.years", 2, 2)
  211. expected = "2 года назад"
  212. if translation != expected {
  213. t.Errorf(`Wrong translation, got %q instead of %q`, translation, expected)
  214. }
  215. translation = printer.Plural("time_elapsed.years", 5, 5)
  216. expected = "5 лет назад"
  217. if translation != expected {
  218. t.Errorf(`Wrong translation, got %q instead of %q`, translation, expected)
  219. }
  220. }
  221. func TestPluralWithMissingTranslation(t *testing.T) {
  222. defaultCatalog = catalog{
  223. "en_US": translationDict{
  224. plurals: map[string][]string{
  225. "number_of_users": {"%d user (%s)", "%d users (%s)"},
  226. },
  227. },
  228. "fr_FR": translationDict{},
  229. }
  230. translation := NewPrinter("fr_FR").Plural("number_of_users", 2)
  231. expected := "number_of_users"
  232. if translation != expected {
  233. t.Errorf(`Wrong translation, got %q instead of %q`, translation, expected)
  234. }
  235. }
  236. func TestPluralWithMissingLanguage(t *testing.T) {
  237. defaultCatalog = catalog{}
  238. translation := NewPrinter("invalid_language").Plural("test.key", 2)
  239. expected := "test.key"
  240. if translation != expected {
  241. t.Errorf(`Wrong translation, got %q instead of %q`, translation, expected)
  242. }
  243. }
  244. func TestPluralWithIndexOutOfBounds(t *testing.T) {
  245. defaultCatalog = catalog{
  246. "test_lang": translationDict{
  247. plurals: map[string][]string{
  248. "limited.key": {"only one form"},
  249. },
  250. },
  251. }
  252. // Force a scenario where getPluralForm might return an index >= len(plurals)
  253. // We'll create a scenario with Czech language rules
  254. defaultCatalog["cs_CZ"] = translationDict{
  255. plurals: map[string][]string{
  256. "limited.key": {"one form only"}, // Only one form, but Czech has 3 plural forms
  257. },
  258. }
  259. printer := NewPrinter("cs_CZ")
  260. // n=5 should return index 2 for Czech, but we only have 1 form (index 0)
  261. translation := printer.Plural("limited.key", 5)
  262. expected := "limited.key"
  263. if translation != expected {
  264. t.Errorf(`Wrong translation for out of bounds index, got %q instead of %q`, translation, expected)
  265. }
  266. }
  267. func TestPluralWithVariousLanguageRules(t *testing.T) {
  268. defaultCatalog = catalog{
  269. "ar_AR": translationDict{
  270. plurals: map[string][]string{
  271. "items": {"no items", "one item", "two items", "few items", "many items", "other items"},
  272. },
  273. },
  274. "pl_PL": translationDict{
  275. plurals: map[string][]string{
  276. "files": {"one file", "few files", "many files"},
  277. },
  278. },
  279. "ja_JP": translationDict{
  280. plurals: map[string][]string{
  281. "photos": {"photos"},
  282. },
  283. },
  284. }
  285. tests := []struct {
  286. language string
  287. key string
  288. n int
  289. expected string
  290. }{
  291. // Arabic tests
  292. {"ar_AR", "items", 0, "no items"},
  293. {"ar_AR", "items", 1, "one item"},
  294. {"ar_AR", "items", 2, "two items"},
  295. {"ar_AR", "items", 5, "few items"}, // n%100 >= 3 && n%100 <= 10
  296. {"ar_AR", "items", 15, "many items"}, // n%100 >= 11
  297. // Polish tests
  298. {"pl_PL", "files", 1, "one file"},
  299. {"pl_PL", "files", 3, "few files"}, // n%10 >= 2 && n%10 <= 4
  300. {"pl_PL", "files", 5, "many files"}, // default case
  301. // Japanese tests (always uses same form)
  302. {"ja_JP", "photos", 1, "photos"},
  303. {"ja_JP", "photos", 10, "photos"},
  304. }
  305. for _, test := range tests {
  306. printer := NewPrinter(test.language)
  307. translation := printer.Plural(test.key, test.n)
  308. if translation != test.expected {
  309. t.Errorf(`Wrong translation for %s with n=%d, got %q instead of %q`,
  310. test.language, test.n, translation, test.expected)
  311. }
  312. }
  313. }