You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

454 lines
11KB

  1. /*
  2. * Copyright (c) 2018 DeineAgentur UG https://www.deineagentur.com. All rights reserved.
  3. * Licensed under the MIT License. See LICENSE file in the project root for full license information.
  4. */
  5. package gotext
  6. import (
  7. "os"
  8. "path"
  9. "testing"
  10. )
  11. func TestLocale(t *testing.T) {
  12. // Set PO content
  13. str := `
  14. msgid ""
  15. msgstr ""
  16. # Initial comment
  17. # Headers below
  18. "Language: en\n"
  19. "Content-Type: text/plain; charset=UTF-8\n"
  20. "Content-Transfer-Encoding: 8bit\n"
  21. "Plural-Forms: nplurals=2; plural=(n != 1);\n"
  22. # Some comment
  23. msgid "My text"
  24. msgstr "Translated text"
  25. # More comments
  26. msgid "Another string"
  27. msgstr ""
  28. msgid "One with var: %s"
  29. msgid_plural "Several with vars: %s"
  30. msgstr[0] "This one is the singular: %s"
  31. msgstr[1] "This one is the plural: %s"
  32. msgstr[2] "And this is the second plural form: %s"
  33. msgid "This one has invalid syntax translations"
  34. msgid_plural "Plural index"
  35. msgstr[abc] "Wrong index"
  36. msgstr[1 "Forgot to close brackets"
  37. msgstr[0] "Badly formatted string'
  38. msgctxt "Ctx"
  39. msgid "One with var: %s"
  40. msgid_plural "Several with vars: %s"
  41. msgstr[0] "This one is the singular in a Ctx context: %s"
  42. msgstr[1] "This one is the plural in a Ctx context: %s"
  43. msgid "Some random"
  44. msgstr "Some random Translation"
  45. msgctxt "Ctx"
  46. msgid "Some random in a context"
  47. msgstr "Some random Translation in a context"
  48. msgid "More"
  49. msgstr "More Translation"
  50. `
  51. // Create Locales directory with simplified language code
  52. dirname := path.Join("/tmp", "en", "LC_MESSAGES")
  53. err := os.MkdirAll(dirname, os.ModePerm)
  54. if err != nil {
  55. t.Fatalf("Can't create test directory: %s", err.Error())
  56. }
  57. // Write PO content to file
  58. filename := path.Join(dirname, "my_domain.po")
  59. f, err := os.Create(filename)
  60. if err != nil {
  61. t.Fatalf("Can't create test file: %s", err.Error())
  62. }
  63. defer f.Close()
  64. _, err = f.WriteString(str)
  65. if err != nil {
  66. t.Fatalf("Can't write to test file: %s", err.Error())
  67. }
  68. // Create Locale with full language code
  69. l := NewLocale("/tmp", "en_US")
  70. // Force nil domain storage
  71. l.Domains = nil
  72. // Add domain
  73. l.AddDomain("my_domain")
  74. // Test translations
  75. tr := l.GetD("my_domain", "My text")
  76. if tr != "Translated text" {
  77. t.Errorf("Expected 'Translated text' but got '%s'", tr)
  78. }
  79. v := "Variable"
  80. tr = l.GetD("my_domain", "One with var: %s", v)
  81. if tr != "This one is the singular: Variable" {
  82. t.Errorf("Expected 'This one is the singular: Variable' but got '%s'", tr)
  83. }
  84. // Test plural
  85. tr = l.GetND("my_domain", "One with var: %s", "Several with vars: %s", 7, v)
  86. if tr != "This one is the plural: Variable" {
  87. t.Errorf("Expected 'This one is the plural: Variable' but got '%s'", tr)
  88. }
  89. // Test context translations
  90. tr = l.GetC("Some random in a context", "Ctx")
  91. if tr != "Some random Translation in a context" {
  92. t.Errorf("Expected 'Some random Translation in a context'. Got '%s'", tr)
  93. }
  94. v = "Test"
  95. tr = l.GetNC("One with var: %s", "Several with vars: %s", 23, "Ctx", v)
  96. if tr != "This one is the plural in a Ctx context: Test" {
  97. t.Errorf("Expected 'This one is the plural in a Ctx context: Test'. Got '%s'", tr)
  98. }
  99. tr = l.GetDC("my_domain", "One with var: %s", "Ctx", v)
  100. if tr != "This one is the singular in a Ctx context: Test" {
  101. t.Errorf("Expected 'This one is the singular in a Ctx context: Test' but got '%s'", tr)
  102. }
  103. // Test plural
  104. tr = l.GetNDC("my_domain", "One with var: %s", "Several with vars: %s", 3, "Ctx", v)
  105. if tr != "This one is the plural in a Ctx context: Test" {
  106. t.Errorf("Expected 'This one is the plural in a Ctx context: Test' but got '%s'", tr)
  107. }
  108. // Test last Translation
  109. tr = l.GetD("my_domain", "More")
  110. if tr != "More Translation" {
  111. t.Errorf("Expected 'More Translation' but got '%s'", tr)
  112. }
  113. }
  114. func TestLocaleFails(t *testing.T) {
  115. // Set PO content
  116. str := `
  117. msgid ""
  118. msgstr ""
  119. # Initial comment
  120. # Headers below
  121. "Language: en\n"
  122. "Content-Type: text/plain; charset=UTF-8\n"
  123. "Content-Transfer-Encoding: 8bit\n"
  124. "Plural-Forms: nplurals=2; plural=(n != 1);\n"
  125. # Some comment
  126. msgid "My text"
  127. msgstr "Translated text"
  128. # More comments
  129. msgid "Another string"
  130. msgstr ""
  131. msgid "One with var: %s"
  132. msgid_plural "Several with vars: %s"
  133. msgstr[0] "This one is the singular: %s"
  134. msgstr[1] "This one is the plural: %s"
  135. msgstr[2] "And this is the second plural form: %s"
  136. msgid "This one has invalid syntax translations"
  137. msgid_plural "Plural index"
  138. msgstr[abc] "Wrong index"
  139. msgstr[1 "Forgot to close brackets"
  140. msgstr[0] "Badly formatted string'
  141. msgid "Invalid formatted id[] with no translations
  142. msgctxt "Ctx"
  143. msgid "One with var: %s"
  144. msgid_plural "Several with vars: %s"
  145. msgstr[0] "This one is the singular in a Ctx context: %s"
  146. msgstr[1] "This one is the plural in a Ctx context: %s"
  147. msgid "Some random"
  148. msgstr "Some random Translation"
  149. msgctxt "Ctx"
  150. msgid "Some random in a context"
  151. msgstr "Some random Translation in a context"
  152. msgid "More"
  153. msgstr "More Translation"
  154. `
  155. // Create Locales directory with simplified language code
  156. dirname := path.Join("/tmp", "en", "LC_MESSAGES")
  157. err := os.MkdirAll(dirname, os.ModePerm)
  158. if err != nil {
  159. t.Fatalf("Can't create test directory: %s", err.Error())
  160. }
  161. // Write PO content to file
  162. filename := path.Join(dirname, "my_domain.po")
  163. f, err := os.Create(filename)
  164. if err != nil {
  165. t.Fatalf("Can't create test file: %s", err.Error())
  166. }
  167. defer f.Close()
  168. _, err = f.WriteString(str)
  169. if err != nil {
  170. t.Fatalf("Can't write to test file: %s", err.Error())
  171. }
  172. // Create Locale with full language code
  173. l := NewLocale("/tmp", "en_US")
  174. // Force nil domain storage
  175. l.Domains = nil
  176. // Add domain
  177. l.AddDomain("my_domain")
  178. // Test non-existent "default" domain responses
  179. tr := l.GetDomain()
  180. if tr != "my_domain" {
  181. t.Errorf("Expected 'my_domain' but got '%s'", tr)
  182. }
  183. // Set default domain to make it fail
  184. l.SetDomain("default")
  185. // Test non-existent "default" domain responses
  186. tr = l.GetDomain()
  187. if tr != "default" {
  188. t.Errorf("Expected 'default' but got '%s'", tr)
  189. }
  190. // Test non-existent "default" domain responses
  191. tr = l.Get("My text")
  192. if tr != "My text" {
  193. t.Errorf("Expected 'My text' but got '%s'", tr)
  194. }
  195. v := "Variable"
  196. tr = l.GetN("One with var: %s", "Several with vars: %s", 2, v)
  197. if tr != "Several with vars: Variable" {
  198. t.Errorf("Expected 'Several with vars: Variable' but got '%s'", tr)
  199. }
  200. // Test inexistent translations
  201. tr = l.Get("This is a test")
  202. if tr != "This is a test" {
  203. t.Errorf("Expected 'This is a test' but got '%s'", tr)
  204. }
  205. tr = l.GetN("This is a test", "This are tests", 1)
  206. if tr != "This are tests" {
  207. t.Errorf("Expected 'This are tests' but got '%s'", tr)
  208. }
  209. // Test syntax error parsed translations
  210. tr = l.Get("This one has invalid syntax translations")
  211. if tr != "This one has invalid syntax translations" {
  212. t.Errorf("Expected 'This one has invalid syntax translations' but got '%s'", tr)
  213. }
  214. tr = l.GetN("This one has invalid syntax translations", "This are tests", 1)
  215. if tr != "This are tests" {
  216. t.Errorf("Expected 'Plural index' but got '%s'", tr)
  217. }
  218. // Create Locale with full language code
  219. l = NewLocale("/tmp", "golem")
  220. // Force nil domain storage
  221. l.Domains = nil
  222. // Add domain
  223. l.SetDomain("my_domain")
  224. // Test non-existent "default" domain responses
  225. tr = l.GetDomain()
  226. if tr != "my_domain" {
  227. t.Errorf("Expected 'my_domain' but got '%s'", tr)
  228. }
  229. // Test syntax error parsed translations
  230. tr = l.Get("This one has invalid syntax translations")
  231. if tr != "This one has invalid syntax translations" {
  232. t.Errorf("Expected 'This one has invalid syntax translations' but got '%s'", tr)
  233. }
  234. tr = l.GetN("This one has invalid syntax translations", "This are tests", 1)
  235. if tr != "This are tests" {
  236. t.Errorf("Expected 'Plural index' but got '%s'", tr)
  237. }
  238. // Create Locale with full language code
  239. l = NewLocale("fixtures/", "fr_FR")
  240. // Force nil domain storage
  241. l.Domains = nil
  242. // Add domain
  243. l.SetDomain("default")
  244. // Test non-existent "default" domain responses
  245. tr = l.GetDomain()
  246. if tr != "default" {
  247. t.Errorf("Expected 'my_domain' but got '%s'", tr)
  248. }
  249. // Test syntax error parsed translations
  250. tr = l.Get("This one has invalid syntax translations")
  251. if tr != "This one has invalid syntax translations" {
  252. t.Errorf("Expected 'This one has invalid syntax translations' but got '%s'", tr)
  253. }
  254. tr = l.GetN("This one has invalid syntax translations", "This are tests", 1)
  255. if tr != "This are tests" {
  256. t.Errorf("Expected 'Plural index' but got '%s'", tr)
  257. }
  258. // Create Locale with full language code
  259. l = NewLocale("fixtures/", "de_DE")
  260. // Force nil domain storage
  261. l.Domains = nil
  262. // Add domain
  263. l.SetDomain("default")
  264. // Test non-existent "default" domain responses
  265. tr = l.GetDomain()
  266. if tr != "default" {
  267. t.Errorf("Expected 'my_domain' but got '%s'", tr)
  268. }
  269. // Test syntax error parsed translations
  270. tr = l.Get("This one has invalid syntax translations")
  271. if tr != "This one has invalid syntax translations" {
  272. t.Errorf("Expected 'This one has invalid syntax translations' but got '%s'", tr)
  273. }
  274. tr = l.GetN("This one has invalid syntax translations", "This are tests", 1)
  275. if tr != "This are tests" {
  276. t.Errorf("Expected 'Plural index' but got '%s'", tr)
  277. }
  278. // Create Locale with full language code
  279. l = NewLocale("fixtures/", "de_AT")
  280. // Force nil domain storage
  281. l.Domains = nil
  282. // Add domain
  283. l.SetDomain("default")
  284. // Test non-existent "default" domain responses
  285. tr = l.GetDomain()
  286. if tr != "default" {
  287. t.Errorf("Expected 'my_domain' but got '%s'", tr)
  288. }
  289. // Test syntax error parsed translations
  290. tr = l.Get("This one has invalid syntax translations")
  291. if tr != "This one has invalid syntax translations" {
  292. t.Errorf("Expected 'This one has invalid syntax translations' but got '%s'", tr)
  293. }
  294. // Test syntax error parsed translations
  295. tr = l.GetNDC("mega", "This one has invalid syntax translations","plural",2,"ctx")
  296. if tr != "plural" {
  297. t.Errorf("Expected 'plural' but got '%s'", tr)
  298. }
  299. tr = l.GetN("This one has invalid syntax translations", "This are tests", 1)
  300. if tr != "This are tests" {
  301. t.Errorf("Expected 'Plural index' but got '%s'", tr)
  302. }
  303. }
  304. func TestLocaleRace(t *testing.T) {
  305. // Set PO content
  306. str := `# Some comment
  307. msgid "My text"
  308. msgstr "Translated text"
  309. # More comments
  310. msgid "Another string"
  311. msgstr ""
  312. msgid "One with var: %s"
  313. msgid_plural "Several with vars: %s"
  314. msgstr[0] "This one is the singular: %s"
  315. msgstr[1] "This one is the plural: %s"
  316. msgstr[2] "And this is the second plural form: %s"
  317. `
  318. // Create Locales directory with simplified language code
  319. dirname := path.Join("/tmp", "es")
  320. err := os.MkdirAll(dirname, os.ModePerm)
  321. if err != nil {
  322. t.Fatalf("Can't create test directory: %s", err.Error())
  323. }
  324. // Write PO content to file
  325. filename := path.Join(dirname, "race.po")
  326. f, err := os.Create(filename)
  327. if err != nil {
  328. t.Fatalf("Can't create test file: %s", err.Error())
  329. }
  330. defer f.Close()
  331. _, err = f.WriteString(str)
  332. if err != nil {
  333. t.Fatalf("Can't write to test file: %s", err.Error())
  334. }
  335. // Create Locale with full language code
  336. l := NewLocale("/tmp", "es")
  337. // Init sync channels
  338. ac := make(chan bool)
  339. rc := make(chan bool)
  340. // Add domain in goroutine
  341. go func(l *Locale, done chan bool) {
  342. l.AddDomain("race")
  343. done <- true
  344. }(l, ac)
  345. // Get translations in goroutine
  346. go func(l *Locale, done chan bool) {
  347. l.GetD("race", "My text")
  348. done <- true
  349. }(l, rc)
  350. // Get translations at top level
  351. l.GetD("race", "My text")
  352. // Wait for goroutines to finish
  353. <-ac
  354. <-rc
  355. }