(root)/
gettext-0.22.4/
gettext-tools/
src/
write-desktop.c
       1  /* Writing Desktop Entry files.
       2     Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009, 2014-2016, 2019-2020 Free Software Foundation, Inc.
       3     This file was written by Daiki Ueno <ueno@gnu.org>.
       4  
       5     This program is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU General Public License as published by
       7     the Free Software Foundation; either version 3 of the License, or
       8     (at your option) any later version.
       9  
      10     This program is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13     GNU General Public License for more details.
      14  
      15     You should have received a copy of the GNU General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  #ifdef HAVE_CONFIG_H
      19  # include <config.h>
      20  #endif
      21  
      22  /* Specification.  */
      23  #include "write-desktop.h"
      24  
      25  #include <assert.h>
      26  #include <errno.h>
      27  #include <stdint.h>
      28  #include <stdlib.h>
      29  #include <stdio.h>
      30  #include "error.h"
      31  #include "msgl-iconv.h"
      32  #include "msgl-header.h"
      33  #include "po-charset.h"
      34  #include "read-catalog.h"
      35  #include "read-po.h"
      36  #include "read-desktop.h"
      37  #include "fwriteerror.h"
      38  #include "xalloc.h"
      39  #include "gettext.h"
      40  
      41  #define _(str) gettext (str)
      42  
      43  typedef struct msgfmt_desktop_reader_ty msgfmt_desktop_reader_ty;
      44  struct msgfmt_desktop_reader_ty
      45  {
      46    DESKTOP_READER_TY
      47    msgfmt_operand_list_ty *operands;
      48    hash_table *keywords;
      49    FILE *output_file;
      50  };
      51  
      52  static void
      53  msgfmt_desktop_handle_group (struct desktop_reader_ty *reader,
      54                               const char *group)
      55  {
      56    msgfmt_desktop_reader_ty *msgfmt_reader = (msgfmt_desktop_reader_ty *) reader;
      57  
      58    fprintf (msgfmt_reader->output_file, "[%s]\n", group);
      59  }
      60  
      61  static void
      62  msgfmt_desktop_handle_pair (desktop_reader_ty *reader,
      63                              lex_pos_ty *key_pos,
      64                              const char *key,
      65                              const char *locale,
      66                              const char *value)
      67  {
      68    msgfmt_desktop_reader_ty *msgfmt_reader = (msgfmt_desktop_reader_ty *) reader;
      69    void *keyword_value;
      70  
      71    if (!locale)
      72      {
      73        /* Write translated pair, if any.  */
      74        if (hash_find_entry (msgfmt_reader->keywords, key, strlen (key),
      75                             &keyword_value) == 0)
      76          {
      77            bool is_list = (bool) (uintptr_t) keyword_value;
      78            char *unescaped = desktop_unescape_string (value, is_list);
      79            size_t i;
      80  
      81            for (i = 0; i < msgfmt_reader->operands->nitems; i++)
      82              {
      83                msgfmt_operand_ty *operand = &msgfmt_reader->operands->items[i];
      84                message_ty *mp;
      85  
      86                mp = message_list_search (operand->mlp, NULL, unescaped);
      87                if (mp && *mp->msgstr != '\0')
      88                  {
      89                    char *escaped;
      90  
      91                    escaped = desktop_escape_string (mp->msgstr, is_list);
      92                    fprintf (msgfmt_reader->output_file,
      93                             "%s[%s]=%s\n",
      94                             key, operand->language, escaped);
      95                    free (escaped);
      96                  }
      97              }
      98            free (unescaped);
      99          }
     100  
     101        /* Write untranslated pair.  */
     102        fprintf (msgfmt_reader->output_file, "%s=%s\n", key, value);
     103      }
     104    else
     105      /* Preserve already translated pair.  */
     106      fprintf (msgfmt_reader->output_file, "%s[%s]=%s\n", key, locale, value);
     107  }
     108  
     109  static void
     110  msgfmt_desktop_handle_comment (struct desktop_reader_ty *reader, const char *s)
     111  {
     112    msgfmt_desktop_reader_ty *msgfmt_reader = (msgfmt_desktop_reader_ty *) reader;
     113  
     114    fputc ('#', msgfmt_reader->output_file);
     115    fputs (s, msgfmt_reader->output_file);
     116    fputc ('\n', msgfmt_reader->output_file);
     117  }
     118  
     119  static void
     120  msgfmt_desktop_handle_blank (struct desktop_reader_ty *reader, const char *s)
     121  {
     122    msgfmt_desktop_reader_ty *msgfmt_reader = (msgfmt_desktop_reader_ty *) reader;
     123  
     124    fputs (s, msgfmt_reader->output_file);
     125    fputc ('\n', msgfmt_reader->output_file);
     126  }
     127  
     128  static desktop_reader_class_ty msgfmt_methods =
     129    {
     130      sizeof (msgfmt_desktop_reader_ty),
     131      NULL,
     132      NULL,
     133      msgfmt_desktop_handle_group,
     134      msgfmt_desktop_handle_pair,
     135      msgfmt_desktop_handle_comment,
     136      msgfmt_desktop_handle_blank
     137    };
     138  
     139  int
     140  msgdomain_write_desktop_bulk (msgfmt_operand_list_ty *operands,
     141                                const char *template_file_name,
     142                                hash_table *keywords,
     143                                const char *file_name)
     144  {
     145    desktop_reader_ty *reader;
     146    msgfmt_desktop_reader_ty *msgfmt_reader;
     147    FILE *template_file;
     148  
     149    reader = desktop_reader_alloc (&msgfmt_methods);
     150    msgfmt_reader = (msgfmt_desktop_reader_ty *) reader;
     151  
     152    msgfmt_reader->operands = operands;
     153    msgfmt_reader->keywords = keywords;
     154  
     155    if (strcmp (file_name, "-") == 0)
     156      msgfmt_reader->output_file = stdout;
     157    else
     158      {
     159        msgfmt_reader->output_file = fopen (file_name, "w");
     160        if (msgfmt_reader->output_file == NULL)
     161          {
     162            desktop_reader_free (reader);
     163            error (0, errno, _("error while opening \"%s\" for writing"),
     164                   file_name);
     165            return 1;
     166          }
     167      }
     168  
     169    template_file = fopen (template_file_name, "r");
     170    if (template_file == NULL)
     171      {
     172        desktop_reader_free (reader);
     173        error (0, errno, _("error while opening \"%s\" for reading"),
     174               template_file_name);
     175        return 1;
     176      }
     177  
     178    desktop_parse (reader, template_file, template_file_name, template_file_name);
     179  
     180    /* Make sure nothing went wrong.  */
     181    if (fwriteerror (msgfmt_reader->output_file))
     182      {
     183        error (0, errno, _("error while writing \"%s\" file"),
     184               file_name);
     185        return 1;
     186      }
     187  
     188    desktop_reader_free (reader);
     189  
     190    return 0;
     191  }
     192  
     193  int
     194  msgdomain_write_desktop (message_list_ty *mlp,
     195                           const char *canon_encoding,
     196                           const char *locale_name,
     197                           const char *template_file_name,
     198                           hash_table *keywords,
     199                           const char *file_name)
     200  {
     201    msgfmt_operand_ty operand;
     202    msgfmt_operand_list_ty operands;
     203  
     204    /* Convert the messages to Unicode.  */
     205    iconv_message_list (mlp, canon_encoding, po_charset_utf8, NULL);
     206  
     207    /* Support for "reproducible builds": Delete information that may vary
     208       between builds in the same conditions.  */
     209    message_list_delete_header_field (mlp, "POT-Creation-Date:");
     210  
     211    /* Create a single-element operands and run the bulk operation on it.  */
     212    operand.language = (char *) locale_name;
     213    operand.mlp = mlp;
     214    operands.nitems = 1;
     215    operands.items = &operand;
     216  
     217    return msgdomain_write_desktop_bulk (&operands,
     218                                         template_file_name,
     219                                         keywords,
     220                                         file_name);
     221  }