# # This file is part of the LibreOffice project. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # # This file incorporates work covered by the following license notice: # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed # with this work for additional information regarding copyright # ownership. The ASF licenses this file to you under the Apache # License, Version 2.0 (the "License"); you may not use this file # except in compliance with the License. You may obtain a copy of # the License at http://www.apache.org/licenses/LICENSE-2.0 . #
"""Translates multiple .desktop files at once with strings from .ulf
files; if you add new translatable .ulf files please add them to
l10ntools/source/localize.cxx in case the module isnot already listed."""
import os import sys import argparse import io
def encode_desktop_string(s_value): """Function encoding strings to be used as values in .desktop files.""" # <https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.1.html# # value-types> says "The escape sequences \s, \n, \t, \r, and \\ are supported for values of # type string and localestring, meaning ASCII space, newline, tab, carriage return, and # backslash, respectively." <https://specifications.freedesktop.org/desktop-entry-spec/ # desktop-entry-spec-1.1.html#basic-format> says "A file is interpreted as a series of lines # that are separated by linefeed characters", so it is apparently necessary to escape at least # linefeed and backslash characters. It is unclear why that spec talks about "linefeed" in # one place and about "newline" ("\n") and "carriage return" ("\r") in another, and how they are # supposed to relate, so just escape any U+000A LINE FEED as "\n" and any U+000D CARRIAGE RETURN # as "\r"; it is unclear exactly which occurrences of U+0020 SPACE and U+0009 CHARACTER # TABULATION would need to be escaped, so they are mostly left unescaped, for readability:
s_value = s_value.replace("\\", "\\\\").replace("\n", "\\n").replace("\r", "\\r") if s_value.startswith(" "): # <https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.1.html# # entries> says "Space before and after the equals sign should be ignored", so escape a # leading U+0020 SPACE as "\s" (while it is not clear whether "space" there means just # U+0020 SPACE or any kind of white space, in which case at least a leading U+0009 CHARACTER # TABULATION should similarly be escaped as "\t"; also, it is unclear whether such # characters should also be escaped at the end):
s_value = "\\s" + s_value[1:] return s_value
if o.template_dir isNone:
template_dir = f"{o.workdir}/{o.prefix}" else:
template_dir = o.template_dir
templates = {}
# open input file
source = io.open(o.ifile, encoding="utf-8")
template = None
# read ulf file for line in source: if line.strip() == "": continue # the headings in the ulf files for .desktop files are in the form [filename_Key] if line[0] == "[":
heading = line.split("]", 1)[0][1:]
template = heading.split("_", 1)[0]
key = heading.split("_", 1)[1]
entry = {} # For every section in the specified ulf file there should exist # a template file in $workdir ..
entry["outfile"] = f"{template_dir}{template}.{o.ext}"
entry["translations"] = {}
entry["key"] = key
templates[heading] = entry else: # split locale = "value" into 2 strings if" = "notin line: continue
locale, value = line.split(" = ")
if locale != line: # replace en-US with en
locale = locale.replace("en-US", "en")
# use just anything inside the "" assert value[0] == '"' # Some entries span multiple lines. # An entry will always end on a double quote. whilenot value.endswith('"\n'):
value += source.readline()
value = value[1:-2]
# replace resource placeholder
value = value.replace("%PRODUCTNAME", o.productname)
locale = locale.replace("-", "_")
templates[heading]["translations"][locale] = value
source.close()
processed = 0 # process templates for template, entries in templates.items():
outfilename = entries["outfile"]
# open the template file - ignore sections for which no # templates exist try:
template_file = io.open(outfilename, encoding="utf-8") except OSError: # string files processed one by one if o.ext == "str": continue
sys.exit(
f"Warning: No template found for item '{template}' : '{outfilename}'\n"
)
processed += 1
# emit the template to the output file for line in template_file:
keyline = line if keyline.startswith(entries["key"]): # hack for Unity section if entries["key"] == "UnityQuickList":
OUTKEY = "Name" else:
OUTKEY = entries["key"]
keyline = OUTKEY + keyline[len(entries["key"]) :]
outfile.write(keyline) if entries["key"] in line:
translations = entries["translations"] for locale in sorted(translations.keys()):
value = translations.get(locale, None) if value: if o.ext in ("desktop", "str"): if o.ext == "desktop":
value = encode_desktop_string(value)
outfile.write(f"{OUTKEY}[{locale}]={value}\n") else:
outfile.write(f"\t[{locale}]{OUTKEY}={value}\n")
template_file.close()
outfile.close() if os.path.exists(outfilename):
os.unlink(outfilename)
os.rename(tmpfilename, outfilename)
if o.ext == "str"and processed == 0:
sys.exit("Warning: No matching templates processed")
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.