WIP Beginning work on (localized) brush descriptions
This commit is contained in:
parent
a2d8b39e95
commit
a266336871
10 changed files with 293 additions and 1 deletions
3
data/brushes/vine.txt
Normal file
3
data/brushes/vine.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Draw with leafy vines.
|
||||
ca.utf8=Dibuixa amb ceps de fulla.
|
||||
ja.utf8=葉の茂った蔓を描きます。
|
||||
|
|
@ -6,7 +6,7 @@ Copyright (c) 2002-2024
|
|||
Various contributors (see below, and AUTHORS.txt)
|
||||
https://tuxpaint.org/
|
||||
|
||||
2024.March.19 (0.9.33)
|
||||
2024.March.25 (0.9.33)
|
||||
* New Magic Tools:
|
||||
----------------
|
||||
* WIP Specular Reflection: Draws a slightly blurred, wavy, and
|
||||
|
|
@ -32,6 +32,11 @@ https://tuxpaint.org/
|
|||
|
||||
* Other Improvements:
|
||||
-------------------
|
||||
* WIP Support for brush descriptions, including localization.
|
||||
(Adds a new "tuxpaint-brushes.pot" & PO files.)
|
||||
Management scripts based on those found in `tuxpaint-stamps`.)
|
||||
Bill Kendrick <bill@newbreedsoftware.com>
|
||||
|
||||
* Make screen refresh more snappy on macOS.
|
||||
Mark Kim <markuskimius@gmail.com>
|
||||
|
||||
|
|
|
|||
11
txt-po/README.txt
Normal file
11
txt-po/README.txt
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
In this directory you'll find scripts for converting description files
|
||||
(e.g. brushes) to and from gettext PO files, for use by translators.
|
||||
|
||||
Run the following two scripts (in this order) everytime a description
|
||||
is added or changed, or a translation (PO file) is updated:
|
||||
|
||||
createpo.sh
|
||||
createtxt.sh
|
||||
|
||||
Note: Never edit the translations in the .txt files,
|
||||
or run the .py scripts directly.
|
||||
28
txt-po/createpo.sh
Executable file
28
txt-po/createpo.sh
Executable file
|
|
@ -0,0 +1,28 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# "createpo.sh" for Tux Paint brush description files
|
||||
# (based on "createpo.sh" from `tuxpaint-stamps`)
|
||||
# Last modified 2024-03-25
|
||||
|
||||
# Generate an updated translation template file for the
|
||||
# descriptions (".pot") based on the main English
|
||||
# strings found in the text description files ("filename.txt").
|
||||
chmod 755 txt2pot.py
|
||||
./txt2pot.py
|
||||
|
||||
# Unify any duplicate translations in the message catalog (".pot")
|
||||
msguniq tuxpaint-brushes.pot | fgrep -v '#-#-#-#-#' > temp.tmp && mv -f temp.tmp tuxpaint-brushes.pot
|
||||
|
||||
# Merge the existing translations with the updated ".pot" file
|
||||
for i in *.po ; do
|
||||
echo $i
|
||||
msgmerge --quiet --update --previous --no-wrap --backup=none $i tuxpaint-brushes.pot
|
||||
# Note: Not using --sort-output, since the POT should be in
|
||||
# the order of the files themselves (by filename),
|
||||
# and that's much more useful than sorting by "msgid".
|
||||
done
|
||||
|
||||
msguniq --no-wrap --to-code=UTF-8 tuxpaint-brushes.pot > temp.tmp && mv -f temp.tmp tuxpaint-brushes.pot
|
||||
|
||||
17
txt-po/createtxt.sh
Executable file
17
txt-po/createtxt.sh
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/sh
|
||||
|
||||
# "createtxt.sh" for Tux Paint text description files
|
||||
# (based on "createtxt.sh" from `tuxpaint-stamps`)
|
||||
# Last modified 2023-03-25
|
||||
|
||||
set -e
|
||||
|
||||
# Unify any duplicate translations
|
||||
for i in *.po* ; do
|
||||
msguniq --no-wrap --to-code=UTF-8 $i > temp.tmp && mv -f temp.tmp $i
|
||||
done
|
||||
|
||||
# Regenerate the description text files ("filename.txt")
|
||||
# from translation files (".po")
|
||||
chmod 755 po2txt.py
|
||||
./po2txt.py
|
||||
110
txt-po/po2txt.py
Executable file
110
txt-po/po2txt.py
Executable file
|
|
@ -0,0 +1,110 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
# po2txt.py for Tux Paint brush description files
|
||||
# (based on "po2txt.py" from `tuxpaint-stamps`)
|
||||
#
|
||||
# Last modified 2024-03-25
|
||||
#
|
||||
# Updates brush description files ("file.txt"),
|
||||
# which contain the textual description of a brush
|
||||
# in English, plus all languages it has been translated to.
|
||||
# This script reads the various localization (".po") files
|
||||
# to fill in the translated lines (e.g., "es=Description in Spanish").
|
||||
# (Those ".po" files are based on a translation template ".pot" file,
|
||||
# which is based on the main English strings found in the ".txt" files;
|
||||
# the script "txt2pot.py" generates the ".pot" file.)
|
||||
|
||||
import sys, os, glob, string
|
||||
|
||||
def lister(dummy, dirname, filesindir):
|
||||
filesindir.sort()
|
||||
for fname in filesindir:
|
||||
fnlist = os.path.splitext(fname)
|
||||
# change the file ext name to .txt whan ready.
|
||||
if fnlist[1] == ".txt":
|
||||
print(">> " + dirname + "/" + fname)
|
||||
# open txt file to read.
|
||||
txtFile = open(os.path.join(dirname, fname), 'rb')
|
||||
# get first line : the description.
|
||||
searchText_unescaped = txtFile.readline()[:-1]
|
||||
searchText_unescaped = searchText_unescaped.decode()
|
||||
print(searchText_unescaped)
|
||||
searchText = searchText_unescaped.replace('"', '\\"')
|
||||
fullsearchText = "msgid \"" + searchText + "\"\n"
|
||||
## print("Searching for <<" + searchText_unescaped + ">>")
|
||||
if searchText in msgidsList:
|
||||
# reopen txt file to write.
|
||||
txtFile = open(os.path.join(dirname, fname), 'wb')
|
||||
# write back the description.
|
||||
## print("Writing back " + searchText_unescaped)
|
||||
txtFile.write((searchText_unescaped + '\n') .encode())
|
||||
# get locale code from the sorted localeList.
|
||||
for locale in localeList:
|
||||
# seek position to the PO file's beginning.
|
||||
localeFiles[locale].seek(0)
|
||||
# search the searchText.
|
||||
noFuzzy = 1
|
||||
line = localeFiles[locale].readline()
|
||||
line = line.decode()
|
||||
while fullsearchText != line:
|
||||
# determine fuzzy.
|
||||
if line[:8] == '#, fuzzy':
|
||||
noFuzzy = 0
|
||||
else:
|
||||
if line[:6] == 'msgstr':
|
||||
noFuzzy = 1
|
||||
line = localeFiles[locale].readline()
|
||||
line = line.decode()
|
||||
# if matched, read the next line, will be translated description.
|
||||
line = localeFiles[locale].readline()
|
||||
line = line.decode()
|
||||
if line[:6] == 'msgstr' and line[8:-2] != "" and noFuzzy:
|
||||
line_sub = line[8:-2]
|
||||
translation_unescaped = line_sub.replace('\\"', '"')
|
||||
txtFile.write(locale.encode() + ".utf8=".encode() + translation_unescaped.encode() + "\n" . encode())
|
||||
txtFile.close()
|
||||
|
||||
def parsePOT(potFileName):
|
||||
try:
|
||||
potFile = open(potFileName, 'rb')
|
||||
except(IOError, e):
|
||||
print("Unable to open the file:" , potFileName, e)
|
||||
print(potFileName)
|
||||
# pass the pot header
|
||||
while len(potFile.readline()) > 1 : pass
|
||||
# parse filename and msgid
|
||||
for line in potFile.readlines():
|
||||
line = line.decode()
|
||||
if line[:5] == 'msgid':
|
||||
# get msgid.
|
||||
msgidsList.append(line[7:-2])
|
||||
# if msgid has more one line,
|
||||
# we need change the way.
|
||||
potFile.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
localeFiles = {}
|
||||
localeList = []
|
||||
msgidsList = []
|
||||
|
||||
# parse pot file to fill msgidsList.
|
||||
parsePOT('./tuxpaint-brushes.pot')
|
||||
|
||||
poFileNames = glob.glob('*.po')
|
||||
for poFileName in poFileNames:
|
||||
# add locale to localeList.
|
||||
localeList.append(poFileName[17:-3])
|
||||
# add po file to localeFiles.
|
||||
localeFiles[poFileName[17:-3]] = open(poFileName, 'rb')
|
||||
|
||||
# sort locale code.
|
||||
localeList.sort()
|
||||
|
||||
# walk around all .txt files.
|
||||
for root, dirs, files in sorted(os.walk('../data/brushes')):
|
||||
lister(None, root, sorted(files))
|
||||
|
||||
# close all po files.
|
||||
for locale in localeList:
|
||||
localeFiles[locale].close()
|
||||
3
txt-po/tuxpaint-brushes-ca.po
Normal file
3
txt-po/tuxpaint-brushes-ca.po
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#: ../data/brushes/vine.txt
|
||||
msgid "Draw with leafy vines."
|
||||
msgstr "Dibuixa amb ceps de fulla."
|
||||
17
txt-po/tuxpaint-brushes-ja.po
Normal file
17
txt-po/tuxpaint-brushes-ja.po
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: tuxpaint-brushes\n"
|
||||
"Report-Msgid-Bugs-To: tuxpaint-i18n@lists.sourceforge.net\n"
|
||||
"POT-Creation-Date: 2024-01-26 07:52:18+0000\n"
|
||||
"PO-Revision-Date: 2024-01-27 11:07+0900\n"
|
||||
"Last-Translator: Shin-ichi TOYAMA <dolphin6k@wmail.plala.or.jp>\n"
|
||||
"Language-Team: Japanese <dolphin6k@wmail.plala.or.jp>\n"
|
||||
"Language: ja\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 3.4.2\n"
|
||||
|
||||
#: ../data/brushes/vine.txt
|
||||
msgid "Draw with leafy vines."
|
||||
msgstr "葉の茂った蔓を描きます。"
|
||||
18
txt-po/tuxpaint-brushes.pot
Normal file
18
txt-po/tuxpaint-brushes.pot
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Tuxpaint-brushes [Language] translation.
|
||||
# Copyright (C) 2024-2024
|
||||
# This file is distributed under the same license as the Tuxpaint package.
|
||||
# [Translator's name] <translator@email.address>, 2024
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: tuxpaint-brushes\n"
|
||||
"Report-Msgid-Bugs-To: tuxpaint-i18n@lists.sourceforge.net\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"POT-Creation-Date: 2024-03-26 03:54:30+0000\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: ../data/brushes/vine.txt
|
||||
msgid "Draw with leafy vines."
|
||||
msgstr ""
|
||||
80
txt-po/txt2pot.py
Executable file
80
txt-po/txt2pot.py
Executable file
|
|
@ -0,0 +1,80 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
# txt2pot.py for Tux Paint text description files
|
||||
# (based on "txt2pot.py" from `tuxpaint-stamps`)
|
||||
#
|
||||
# Last modified 2024-03-25
|
||||
#
|
||||
# Updates description localization template (".pot")
|
||||
# to capture any new strings, or changes to the main English
|
||||
# translations, found within the brush description files
|
||||
# ("filename.txt"), which contain both the textual description
|
||||
# of the brush in English, plus all languages it has been translated to.
|
||||
# (As generated by "po2txt.py").
|
||||
|
||||
import sys, os, string
|
||||
from time import gmtime, strftime
|
||||
|
||||
poHeader="""# Tuxpaint-brushes [Language] translation.
|
||||
# Copyright (C) 2024-""".encode()+\
|
||||
strftime("%Y", gmtime()).encode()+"\n".encode()+\
|
||||
"""# This file is distributed under the same license as the Tuxpaint package.
|
||||
# [Translator's name] <translator@email.address>, """.encode()+\
|
||||
strftime("%Y", gmtime()).encode()+"\n"\
|
||||
"""#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: tuxpaint-brushes\\n"
|
||||
"Report-Msgid-Bugs-To: tuxpaint-i18n@lists.sourceforge.net\\n"
|
||||
"MIME-Version: 1.0\\n"
|
||||
"POT-Creation-Date: """.encode()+\
|
||||
strftime("%Y-%m-%d %H:%M:%S+0000", gmtime()).encode()+"\\n\"\n"\
|
||||
""""PO-Revision-Date: \\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\\n"
|
||||
"Content-Transfer-Encoding: 8bit\\n"
|
||||
""".encode()
|
||||
localeList = []
|
||||
|
||||
|
||||
def lister(poLocale, dirname, filesindir):
|
||||
filesindir.sort()
|
||||
for fname in filesindir:
|
||||
fnlist = os.path.splitext(fname)
|
||||
if fnlist[1] == ".txt":
|
||||
print(dirname + "/" + fname)
|
||||
txtFile = open(os.path.join(dirname, fname), 'rb')
|
||||
# write filename down follow mark('#').
|
||||
poFile.write(('\n#: ' + dirname + '/' + fnlist[0] + fnlist[1] + '\n').encode())
|
||||
# write description in msgid.
|
||||
line = txtFile.readline().decode()
|
||||
if line[-1:] == "\n" :
|
||||
line = line[:-1]
|
||||
line = line.replace('"', '\\"')
|
||||
print(" ==> <<" + line + ">>")
|
||||
poFile.write(('msgid "' + line + '"\n').encode())
|
||||
localeString = ""
|
||||
for lineEnc in txtFile.readlines():
|
||||
line = lineEnc.decode()
|
||||
# replace " to \"
|
||||
line = line.replace('"', '\\"')
|
||||
splitup = line.find('.utf8')
|
||||
if splitup != -1 and line[0] != '#' :
|
||||
locale = line[:splitup]
|
||||
if locale not in localeList:
|
||||
localeList.append(locale)
|
||||
if locale == poLocale:
|
||||
localeString = line[string.find(line, "=") + 1:-1]
|
||||
txtFile.close()
|
||||
# write translation or empty string in msgstr.
|
||||
poFile.write(('msgstr "' + localeString + '"\n').encode())
|
||||
|
||||
if __name__ == '__main__':
|
||||
poFile = open('./tuxpaint-brushes.pot', 'wb')
|
||||
print(">>", poFile.name)
|
||||
poFile.write(poHeader)
|
||||
|
||||
for root, dirs, files in sorted(os.walk('../data/brushes')):
|
||||
lister(None, root, sorted(files))
|
||||
|
||||
poFile.close()
|
||||
Loading…
Add table
Add a link
Reference in a new issue