poe

Уређивач .po фајлова
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

чување bdd98bcdf8ff66c16b009fde7fa5f3234815bc33
родитељ 4cd6e1ac30dc31e4bcaa7d5faabe4ff31b7aa0c7
Аутор: Страхиња Радић <contact@strahinja.org>
Датум:   Sun, 11 Jul 2021 21:00:09 +0200

Fix: correct save of obsolete messages and plural msgstrs when they are untranslated; moved the code to open edit box into separate function

Signed-off-by: Страхиња Радић <contact@strahinja.org>

Diffstat:
MREADME | 4++++
Mdraw.c | 44++++++++++++++++++++++++++++++++++++++++++++
Mdraw.h | 2++
Mpo.c | 51+++++++++++++++++++++++++++++++++++++++++----------
Mpo.h | 2+-
Mpoe.c | 144+++++++++++++++++++++++++++++--------------------------------------------------
Mtest/sr.po | 4++--
измењених датотека: 7, додавања: 147(+), брисања: 104(-)

diff --git a/README b/README @@ -12,6 +12,10 @@ A: See TODO for a list of implemented and planned features. Q: Why C? A: Because <Go/Rust/whatever soydev language of the moment> sucks. +Q: Why is poe saying there are <N+1> messages in my file when + other editors say there are <N> messages? +A: Because poe counts (and allows editing of) the first, special msgid. + License ------- diff --git a/draw.c b/draw.c @@ -1,4 +1,5 @@ /* See the file LICENSE for copyright and license details. */ +#include <errno.h> #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -100,6 +101,7 @@ init_drawstate(struct DrawState* state, char* error, char* filename, state->search_column = 0; state->search_first_shown_column = 0; state->search_display_column = 0; + state->nplurals = 2; state->prompt = prompt; state->prompt_callback = NULL; state->running = 1; @@ -158,6 +160,48 @@ free_drawstate(struct DrawState* state) } } +struct DrawState* +set_nplurals(struct DrawState* state, struct PoEntry* entry) +{ + if (!entry || !entry->plural_forms) + return NULL; + + int read_number = 0; + uint32_t* ppf = entry->plural_forms; + char token[MAXBUFLINE]; + char* ptoken = token; + + *ptoken = 0; + while (*ppf) + { + if (u32_starts_with(ppf, (uint32_t*)L"nplurals=")) + { + ppf += strlen("nplurals="); + read_number = 1; + } + else if (read_number && *ppf >= '0' && *ppf <= '9') + { + *ptoken++ = *ppf++; + } + else if (read_number && *ppf == ';') + { + *ptoken = 0; + ptoken = token; + break; + } + else + ppf++; + } + if (*ptoken) + { + state->nplurals = strtol(ptoken, NULL, 0); + if (errno) + return NULL; + } + + return state; +} + struct BufferLine* split(const uint32_t* s) { diff --git a/draw.h b/draw.h @@ -62,6 +62,7 @@ struct DrawState { int search_first_shown_column; int search_display_column; struct PoEntry* entries; + long nplurals; void (*prompt_callback)(struct DrawState*, struct tb_event*); int running; int dirty; @@ -100,6 +101,7 @@ void free_bufferline(struct BufferLine* bl); void init_drawstate(struct DrawState* state, char* error, char* filename, char* prompt); void free_drawstate(struct DrawState* state); +struct DrawState* set_nplurals(struct DrawState* state, struct PoEntry* entry); struct BufferLine* split(const uint32_t* s); size_t display_length(const struct DrawState* state, uint32_t* buffer, const size_t max_index); diff --git a/po.c b/po.c @@ -374,8 +374,13 @@ load_file(struct DrawState* dstate, long* lineno, long* col) fclose(input); /* when the .po file is not a standard text file (no LF at end) */ - if (dstate->msgid_count > 1 && entry->msgid) - dstate->msgid_count++; + if (dstate->msgid_count > 1) + { + if (entry->msgid) + dstate->msgid_count++; + else if (entry->obsolete) + dstate->obsolete_count++; + } else dstate->untranslated_count--; @@ -390,7 +395,7 @@ load_file(struct DrawState* dstate, long* lineno, long* col) int save_file(const struct PoEntry* entries, const size_t real_msgid_count, - const char* filename) + const char* filename, const int nplurals) { const struct PoEntry* current = entries; size_t len = strlen(filename); @@ -418,7 +423,9 @@ save_file(const struct PoEntry* entries, const size_t real_msgid_count, unicode_string_to_u8(u8_comment, *(current->comments + c), MAXCOMMENTLINE * 6); - fprintf(output, "#%s\n", u8_comment); + fprintf(output, "#%s%s\n", + current->obsolete ? "~" : "", + u8_comment); } } if (current->trans_comment_lines > 0) @@ -475,6 +482,13 @@ save_file(const struct PoEntry* entries, const size_t real_msgid_count, if (current->flags != FL_NONE) fprintf(output, "\n"); + if (current->obsolete) + { + fprintf(output, "\n"); + current++; + continue; + } + if (current->msgid) { char msgid[MAXMSG]; @@ -638,6 +652,11 @@ save_file(const struct PoEntry* entries, const size_t real_msgid_count, } free(msgstr_split); } + else if (current->msgid_plural && + (!*current->msgstr || + !**current->msgstr)) + for (int i = 0; i < nplurals; i++) + fprintf(output, "msgstr[%d] \"\"\n", i); else { char u8_msgstr[MAXMSG*6]; @@ -701,7 +720,13 @@ save_file(const struct PoEntry* entries, const size_t real_msgid_count, } } else - fprintf(output, "msgstr \"\"\n"); + { + if (current->msgid_plural) + for (int i = 0; i < nplurals; i++) + fprintf(output, "msgstr[%d] \"\"\n", i); + else + fprintf(output, "msgstr \"\"\n"); + } fprintf(output, "\n"); current++; @@ -888,7 +913,8 @@ parse_po_line(const char* line, struct DrawState* dstate, /* skip beginning and end quote */ if ((ptoken == token || *(pline+1) == 0) && !(*pstate & (PS_COMMENT_TRAN - | PS_COMMENT_EXTR))) + | PS_COMMENT_EXTR + | PS_COMMENT_OBSO))) { pline++; (*col)++; @@ -942,11 +968,16 @@ parse_po_line(const char* line, struct DrawState* dstate, set_msgid_plural(*current_entry, token, 1); else if (*pstate & PS_MSGSTR) { - if (*current_entry == dstate->entries && - starts_with(token, - "Plural-Forms: ")) - set_plural_forms(*current_entry, token + + /* first entry */ + if (*current_entry == dstate->entries) + { + if (starts_with(token, "Plural-Forms: ")) + { + set_plural_forms(*current_entry, token + strlen("Plural-Forms: "), 0); + set_nplurals(dstate, *current_entry); + } + } set_msgstr(*current_entry, token, 0, 1, dstate); } else if (*pstate & PS_MSGSTR_ARRAY) diff --git a/po.h b/po.h @@ -109,7 +109,7 @@ struct PoEntry* u32_add_trans_comment(struct PoEntry* entry, struct PoEntry* add_ref_comment(struct PoEntry* entry, const char* comment); int load_file(struct DrawState* state, long* lineno, long* col); int save_file(const struct PoEntry* entries, const size_t real_msgid_count, - const char* filename); + const char* filename, const int nplurals); int parse_po_line(const char* line, struct DrawState* dstate, struct PoEntry** current_entry, ParseState* pstate, long* col, int* msgstr_index); diff --git a/poe.c b/poe.c @@ -53,6 +53,7 @@ void next_match(struct DrawState* state); void prev_match(struct DrawState* state); void next_untranslated(struct DrawState* state); void next_fuzzy(struct DrawState* state); +void show_edit(struct DrawState* state); void move_up(struct DrawState* state); void move_down(struct DrawState* state); void edit_page_up(struct DrawState* state); @@ -146,7 +147,7 @@ quit_callback(struct DrawState* state, struct tb_event* ev) { int result = save_file(state->entries, state->real_msgid_count, - state->filename); + state->filename, state->nplurals); switch (result) { case SAVE_ERR_CANT_ALLOC: @@ -781,7 +782,7 @@ erase_search_prev_word(struct DrawState* state) struct DrawState* copy_msgid_to_input(struct DrawState* state) { - if (state->edit_info_focused) + if (state->edit_info_focused || state->msgid_number == 1) return state; struct PoEntry* current = &state->entries[state->msgid_number-1]; size_t msgid_num_lines = u32_lines_in_string(current->msgid); @@ -918,14 +919,15 @@ next_untranslated(struct DrawState* state) if (!current->msgstr || !*current->msgstr || u32_strlen(*current->msgstr) == 0) { - if (state->show_edit) + int save_show_edit = state->show_edit; + if (save_show_edit) { - save_msgstr(state); - state->dirty_before_edit = state->dirty; - state->fuzzy_before_edit = state->fuzzy_count; - state->input_changed_fuzzy = UNCHANGED; - } - + if (state->dirty) + save_msgstr(state); + else + state->dirty = state->dirty_before_edit; + } + state->msgid_number = e + 1; if (state->msgid_number < (state->maxy-1)/2) state->first_shown_msgid = @@ -938,18 +940,10 @@ next_untranslated(struct DrawState* state) state->first_shown_msgid = state->msgid_number - (state->maxy-1)/2; - if (state->show_edit) + if (save_show_edit) { state->msgstr_index = 0; - load_msgstr(state); - load_info(state); - state->input_row = 0; - state->input_first_shown_row = 0; - state->input_first_shown_column = 0; - state->info_first_shown_row = 0; - state->info_first_shown_column = 0; - move_start(state); - state->error[0] = 0; + show_edit(state); } return; @@ -971,14 +965,15 @@ next_fuzzy(struct DrawState* state) current = state->entries + e; if (current->flags & FL_FUZZY) { - if (state->show_edit) + int save_show_edit = state->show_edit; + if (save_show_edit) { - save_msgstr(state); - state->dirty_before_edit = state->dirty; - state->fuzzy_before_edit = state->fuzzy_count; - state->input_changed_fuzzy = UNCHANGED; - } - + if (state->dirty) + save_msgstr(state); + else + state->dirty = state->dirty_before_edit; + } + state->msgid_number = e + 1; if (state->msgid_number < (state->maxy-1)/2) state->first_shown_msgid = @@ -991,18 +986,10 @@ next_fuzzy(struct DrawState* state) state->first_shown_msgid = state->msgid_number - (state->maxy-1)/2; - if (state->show_edit) + if (save_show_edit) { state->msgstr_index = 0; - load_msgstr(state); - load_info(state); - state->input_row = 0; - state->input_first_shown_row = 0; - state->input_first_shown_column = 0; - state->info_first_shown_row = 0; - state->info_first_shown_column = 0; - move_start(state); - state->error[0] = 0; + show_edit(state); } return; @@ -1011,6 +998,30 @@ next_fuzzy(struct DrawState* state) } void +show_edit(struct DrawState* state) +{ + if (load_msgstr(state) && load_info(state)) + { + state->dirty_before_edit = state->dirty; + state->fuzzy_before_edit = state->fuzzy_count; + state->input_changed_fuzzy = UNCHANGED; + state->show_edit = 1; + state->input_row = 0; + state->input_first_shown_row = 0; + state->input_first_shown_column = 0; + state->info_first_shown_row = 0; + state->info_first_shown_column = 0; + move_start(state); + state->error[0] = 0; + } + else + { + strcpy(state->error, errors[ERR_CANT_ALLOC]); + state->running = 0; + } +} + +void move_up(struct DrawState* state) { if (state->edit_info_focused) @@ -1100,26 +1111,12 @@ edit_page_up(struct DrawState* state) } if (state->dirty) - { save_msgstr(state); - state->dirty_before_edit = 1; - } else state->dirty = state->dirty_before_edit; - state->fuzzy_before_edit = state->fuzzy_count; - state->input_changed_fuzzy = UNCHANGED; - state->show_edit = 1; move_list_up(state); state->msgstr_index = 0; - load_msgstr(state); - load_info(state); - state->input_row = 0; - state->input_first_shown_row = 0; - state->input_first_shown_column = 0; - state->info_first_shown_row = 0; - state->info_first_shown_column = 0; - move_start(state); - state->error[0] = 0; + show_edit(state); } void @@ -1134,27 +1131,12 @@ edit_page_down(struct DrawState* state) } if (state->dirty) - { save_msgstr(state); - state->dirty_before_edit = 1; - } else state->dirty = state->dirty_before_edit; - state->dirty = state->dirty_before_edit; - state->fuzzy_before_edit = state->fuzzy_count; - state->input_changed_fuzzy = UNCHANGED; - state->show_edit = 1; move_list_down(state); state->msgstr_index = 0; - load_msgstr(state); - load_info(state); - state->input_row = 0; - state->input_first_shown_row = 0; - state->input_first_shown_column = 0; - state->info_first_shown_row = 0; - state->info_first_shown_column = 0; - move_start(state); - state->error[0] = 0; + show_edit(state); } void @@ -1409,8 +1391,7 @@ next_plural(struct DrawState* state) save_msgstr(state); if (state->msgstr_index + 1 < current->msgstr_count) state->msgstr_index++; - load_msgstr(state); - load_info(state); + show_edit(state); } void @@ -1421,8 +1402,7 @@ prev_plural(struct DrawState* state) save_msgstr(state); if (state->msgstr_index > 0) state->msgstr_index--; - load_msgstr(state); - load_info(state); + show_edit(state); } void @@ -1822,7 +1802,7 @@ handle_key_event(struct tb_event* ev, struct DrawState* state) if (!state->dirty) return; int result = save_file(state->entries, state->real_msgid_count, - state->filename); + state->filename, state->nplurals); switch (result) { case SAVE_ERR_CANT_ALLOC: @@ -1854,25 +1834,7 @@ handle_key_event(struct tb_event* ev, struct DrawState* state) else { state->msgstr_index = 0; - if (load_msgstr(state) && load_info(state)) - { - state->dirty_before_edit = state->dirty; - state->fuzzy_before_edit = state->fuzzy_count; - state->input_changed_fuzzy = UNCHANGED; - state->show_edit = 1; - state->input_row = 0; - state->input_first_shown_row = 0; - state->input_first_shown_column = 0; - state->info_first_shown_row = 0; - state->info_first_shown_column = 0; - move_start(state); - state->error[0] = 0; - } - else - { - strcpy(state->error, errors[ERR_CANT_ALLOC]); - state->running = 0; - } + show_edit(state); } } else if (ev->key == TB_KEY_F1 || ev->ch == 'H') diff --git a/test/sr.po b/test/sr.po @@ -10,7 +10,7 @@ msgstr "" "Project-Id-Version: neomutt 20210205\n" "Report-Msgid-Bugs-To: neomutt-devel@neomutt.org\n" "POT-Creation-Date: 2021-06-19 23:57+0100\n" -"PO-Revision-Date: 2021-07-06 14:33+0200\n" +"PO-Revision-Date: 2021-07-11 20:17+0200\n" "Last-Translator: Страхиња Радић <contact@strahinja.org>\n" "Language-Team: Serbian <sr@li.org>\n" "Language: sr\n" @@ -18,7 +18,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -"X-Generator: poe v0.4.1-alpha-10-gee87d9d\n" +"X-Generator: poe v0.5-alpha-8-g4cd6e1a\n" #. L10N: prompt to add a new alias #: alias/alias.c:397