чување 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:
| M | README | | | 4 | ++++ |
| M | draw.c | | | 44 | ++++++++++++++++++++++++++++++++++++++++++++ |
| M | draw.h | | | 2 | ++ |
| M | po.c | | | 51 | +++++++++++++++++++++++++++++++++++++++++---------- |
| M | po.h | | | 2 | +- |
| M | poe.c | | | 144 | +++++++++++++++++++++++++++++-------------------------------------------------- |
| M | test/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