From 6139da3d41b9e1c2eebd5f323bb0126775233d1b Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Fri, 17 May 2024 14:15:56 +0200 Subject: [PATCH] Fix .mo contexts Fixes #3590 - `get("key")` - `get("context", "key")` --- core/text/i18n/gettext.odin | 38 +++++++++++------- tests/core/assets/I18N/mixed_context.mo | Bin 0 -> 476 bytes tests/core/assets/I18N/mixed_context.po | 18 +++++++++ tests/core/assets/I18N/plur.po | 17 ++++++++ tests/core/text/i18n/test_core_text_i18n.odin | 14 +++++++ 5 files changed, 72 insertions(+), 15 deletions(-) create mode 100644 tests/core/assets/I18N/mixed_context.mo create mode 100644 tests/core/assets/I18N/mixed_context.po create mode 100644 tests/core/assets/I18N/plur.po diff --git a/core/text/i18n/gettext.odin b/core/text/i18n/gettext.odin index 6b8f52861..35d355a40 100644 --- a/core/text/i18n/gettext.odin +++ b/core/text/i18n/gettext.odin @@ -60,10 +60,6 @@ parse_mo_from_bytes :: proc(data: []byte, options := DEFAULT_PARSE_OPTIONS, plur translation.pluralize = pluralizer strings.intern_init(&translation.intern, allocator, allocator) - // Gettext MO files only have one section. - translation.k_v[""] = {} - section := &translation.k_v[""] - for n := u32(0); n < count; n += 1 { /* Grab string's original length and offset. @@ -83,37 +79,49 @@ parse_mo_from_bytes :: proc(data: []byte, options := DEFAULT_PARSE_OPTIONS, plur max_offset := int(max(o_offset + o_length + 1, t_offset + t_length + 1)) if len(data) < max_offset { return translation, .Premature_EOF } - key := data[o_offset:][:o_length] - val := data[t_offset:][:t_length] + key_data := data[o_offset:][:o_length] + val_data := data[t_offset:][:t_length] /* Could be a pluralized string. */ zero := []byte{0} - - keys := bytes.split(key, zero) - vals := bytes.split(val, zero) + keys := bytes.split(key_data, zero); defer delete(keys) + vals := bytes.split(val_data, zero); defer delete(vals) if (len(keys) != 1 && len(keys) != 2) || len(vals) > MAX_PLURALS { return translation, .MO_File_Incorrect_Plural_Count } + section_name := "" for k in keys { - interned_key, _ := strings.intern_get(&translation.intern, string(k)) + key := string(k) + // Scan for EOT + for ch, i in k { + if ch == 0x04 { + section_name = string(k[:i]) + key = string(k[i+1:]) + break + } + } + section_name, _ = strings.intern_get(&translation.intern, section_name) + if section_name not_in translation.k_v { + translation.k_v[section_name] = {} + } + + interned_key, _ := strings.intern_get(&translation.intern, string(key)) interned_vals := make([]string, len(vals)) last_val: string - i := 0 - for v in vals { + for v, i in vals { interned_vals[i], _ = strings.intern_get(&translation.intern, string(v)) last_val = interned_vals[i] - i += 1 } + + section := &translation.k_v[section_name] section[interned_key] = interned_vals } - delete(vals) - delete(keys) } return } diff --git a/tests/core/assets/I18N/mixed_context.mo b/tests/core/assets/I18N/mixed_context.mo new file mode 100644 index 0000000000000000000000000000000000000000..53efee09ab6ae90e39ccfaf6304e25042a436a45 GIT binary patch literal 476 zcmca7#4?qEfq{XUfq_AWfq}t$Gh7={{73U{)8FTFG|Jyka(H8Iyp!8I>EC$l&ME^MWcniucs%H`|n>xys_$VFgZZnMN(!7S3pi_ zQDTm+TYgb)v6Vtz0hn8CYh\n" +"Language-Team: English\n" +"Language: en_IE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "Context" +msgid "Message1" +msgstr "This is message 1 with Context" + +msgid "Message1" +msgstr "This is message 1 without Context" diff --git a/tests/core/assets/I18N/plur.po b/tests/core/assets/I18N/plur.po new file mode 100644 index 000000000..45c8209ca --- /dev/null +++ b/tests/core/assets/I18N/plur.po @@ -0,0 +1,17 @@ +msgid "" +msgstr "" +"Project-Id-Version: 0.1.0\n" +"PO-Revision-Date: 2024-04-13 11:13+0200\n" +"Last-Translator: Someone \n" +"Language-Team: English\n" +"Language: it_IT\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2);\n" + +msgid "Message1" +msgid_plural "Message1/plural" +msgstr[0] "This is message 1" +msgstr[1] "This is message 1 - plural A" +msgstr[2] "This is message 1 - plural B" diff --git a/tests/core/text/i18n/test_core_text_i18n.odin b/tests/core/text/i18n/test_core_text_i18n.odin index d59f5a382..11d2f9c0c 100644 --- a/tests/core/text/i18n/test_core_text_i18n.odin +++ b/tests/core/text/i18n/test_core_text_i18n.odin @@ -72,6 +72,20 @@ TESTS := []Test_Suite{ }, }, + { + file = "assets/I18N/mixed_context.mo", + loader = i18n.parse_mo_file, + plural = nil, + tests = { + // These are in the catalog. + {"", "Message1", "This is message 1 without Context", 1}, + {"Context", "Message1", "This is message 1 with Context", 1}, + + // This isn't in the catalog, so should ruturn the key. + {"", "Come visit us on Discord!", "Come visit us on Discord!", 1}, + }, + }, + { file = "assets/I18N/nl_NL.mo", loader = i18n.parse_mo_file,