script and README #4

Merged
friendicaproject merged 1 commit from tobias/git.friendi.ca:master into master 2018-06-11 08:41:16 +02:00
2 changed files with 218 additions and 1 deletions

View file

@ -1,8 +1,26 @@
# Custom files for git.friendi.ca
These files are the cutsom files for git.friendi.ca.
They are overriding the default template files of gitea
They are overriding the default template files of gitea.
The content of `custom` needs to be placed in `/var/lib/gitea` (at least at git.friendi.ca).
## Translation
Translation of the strings can be done at [Transifex](https://www.transifex.com/Friendica/friendica/) with the rest of the project resources.
## Workflow
1. Update the strings at the top of the `generate_home_tmpl.py` file, those that start with a `str_` in the name.
2. Extract them with `pygettext -p ./lang/C/ generate_home_tmpl.py`
3. Commit the new `messages.pot` file and push it to the repository at git.friendi.ca
4. Wait for Transifex to pick up the changes and the translation teams to make the new translations
5. Download the finished translations to `lang/$lngcode/LC_MESSAGES/messages.pot`
6. Edit the `messages.pot` file and set the characterset to UTF-8.
`"Content-Type: text/plain; charset=UTF-8\n"`
7. Convert the `messages.pot` file to `messages.mo` using `msgfmt messages.pot`
8. Run `python3 generate_home_tmpl.py` it will recreate the `custom/templates/home.tmpl` file
9. Upload that file and copy it to the `custom/templates/` directory of the gitea instance.
## License
The python script to generate the template file has been released under the terms of the MIT license.

199
generate_home_tmpl.py Normal file
View file

@ -0,0 +1,199 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Script to generate the gitea landing page for git.friendi.ca with strings
from the translation files. The generated 'home.tmpl' then has to be
placed into the 'custom/templates' directory of the gitea installation.
Authors:
* Tobias Diekershoff <tobias.diekershoff(@)gmx.net>
Copyright (c) 2018
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
import gettext
import os
# define dummy _ function for pygettext to find the translate-able strings
def _(message): return message
# constant strings for the webpage
str_collection = _("Collection of the git repositories of the <a href='https://friendi.ca' target='_new'>Friendica</a> project.")
str_header1 = _("Easy to install")
str_box1 = _("All you need is PHP and a MySQL database. Installation can be done via file upload, git or docker.")
str_header2 = _("Free Software")
str_box2 = _("Friendica is Free Software, licensed under the terms of the AGPLv3 (or later). The entire source code is hosted at <a href='https://git.friendi.ca/friendica/friendica'>git.friendi.ca</a>. Join us by contributing to make this project even better. Don't be shy to <a href='https://git.friendi.ca/friendica/friendica/src/branch/develop/doc/Developers-Intro.md'>be a contributor</a>!")
str_header3 = _("Decentralization")
str_box3 = _("Decentralized architecture with no central authority or ownership. Relationships can be made across any compatible system, creating a network of Internet scale made up of smaller sites. Seamless wall-to-wall posts and remote comments, even across different network nodes.")
str_header4 = _("Interoperability")
str_box4 = _("Friendica has build in support for the OStatus (e.g. GNU social and Mastodon) and diaspora* (e.g. diaspora*, Hubzilla and Socialhome) protocol. With additional addons you can bridge to more networks like pump.io, Twitter and others.")
# we don't need the dummy anymore
del _
# which translations do we have? and where to find them
myDomain = "messages"
languageDirectory = 'lang'
fn = os.path.join(os.path.abspath(os.path.dirname(__file__)), languageDirectory)
# once there are translations, this list is used to hold the lng-codes
# of the available translations. Later in the script, when the home.tmpl
# is created, we'll loop over all these languages.
translations = ['de-DE', 'nl-NL', 'it-IT', 'pl-PL', 'cs-CZ']
count = len(translations)
languages = {}
# read in all the available translation for later usage
for lng in translations:
l = gettext.translation(domain=myDomain, localedir=fn, languages=[lng])
languages[lng] = l
# for the beginning and ending of the if ... else if ... else cascade
ifelse = {0: '\n{{if eq .Lang "{{lngcode}}"}}\n', count: '\n{{else}}\n'}
# The icons from font awesome used for the four info box titles
icons = {'ul' : '<i class="octicon octicon-rocket"></i>',
'ur' : '<i class="octicon octicon-code"></i>',
'll' : '<i class="octicon octicon-globe"></i>',
'lr' : '<i class="octicon octicon-organization"></i>'}
# header block of the template
templateHead = """{{template "base/head" .}}
<div class="home">
<div class="ui stackable middle very relaxed page grid">
<div class="sixteen wide center aligned centered column">
<div>
<img class="logo" src="{{AppSubUrl}}/img/friendica-128.png" />
</div>
<div class="hero">
<h1 class="ui icon header title">
Friendica
</h1>
"""
# template for the subtitle in the header
templateCollection = " <h2>{{CollectionOfRepositories}}</h2>"
# closing the header
templateMedium = """
</div>
</div>
</div>
"""
# The info boxes, there are four in total, this template holds 2 divs (left and right)
templateInfoBox = """ <div class="ui stackable middle very relaxed page grid">
<div class="eight wide center column">
<h1 class="hero ui icon header">
{{Licon}} {{Lheader}}
</h1>
<p class="large">
{{Lbody}}
</p>
</div>
<div class="eight wide center column">
<h1 class="hero ui icon header">
{{Ricon}} {{Rheader}}
</h1>
<p class="large">
{{Rbody}}
</p>
</div>
</div>
"""
# closing the page
templateFooter = """</div>
{{template "base/footer" .}}
"""
# templates and preparation done, generate the home.tmpl file containing all ready languages
with open('custom/templates/home.tmpl', mode='w', encoding='utf-8') as outFile:
outFile.write(templateHead)
if count:
for i in range(count+1):
try:
# for all languages except the default
lng = translations[i]
l = languages[translations[i]]
_ = l.gettext
l.install()
outString = _(str_collection)
except:
# last entry in the cascade is the default (EN) language
lng = 'en'
outString = str_collection
if i in [0, count]:
# opening and ending of the if ... else if ... else cascade need special treatment
outFile.write(ifelse[i].replace('{{lngcode}}', lng))
else:
outFile.write('\n{{else if eq .Lang "{{lngcode}}"}}\n'.replace('{{lngcode}}', lng))
outFile.write(templateCollection.replace("{{CollectionOfRepositories}}", outString))
outFile.write('\n{{end}}\n')
else:
# if not, we just take the line for the base language
outFile.write(templateCollection.replace("{{CollectionOfRepositories}}", str_collection))
outFile.write(templateMedium)
# now add the info boxes in all translations and the base language
if count:
for i in range(count+1):
try:
lng = translations[i]
l = languages[translations[i]]
_ = l.gettext
l.install()
except:
lng = 'en'
if i in [0, count]:
# opening and ending of the if ... else if ... else cascade need special treatment
outFile.write(ifelse[i].replace('{{lngcode}}', lng))
else:
outFile.write('\n{{else if eq .Lang "{{lngcode}}"}}\n'.replace('{{lngcode}}', lng))
if not i == count:
# a translation
# upper row of info boxes
tmpText = templateInfoBox.replace('{{Licon}}', icons['ul']).replace('{{Ricon}}', icons['ur'])
tmpText = tmpText.replace('{{Lheader}}', _(str_header1)).replace('{{Rheader}}', _(str_header2))
tmpText = tmpText.replace('{{Lbody}}', _(str_box1)).replace('{{Rbody}}', _(str_box2))
outFile.write(tmpText)
# lower row of info boxes
tmpText = templateInfoBox.replace('{{Licon}}', icons['ll']).replace('{{Ricon}}', icons['lr'])
tmpText = tmpText.replace('{{Lheader}}', _(str_header3)).replace('{{Rheader}}', _(str_header4))
tmpText = tmpText.replace('{{Lbody}}', _(str_box3)).replace('{{Rbody}}', _(str_box4))
outFile.write(tmpText)
else:
# finally the default language
# upper row of info boxes
tmpText = templateInfoBox.replace('{{Licon}}', icons['ul']).replace('{{Ricon}}', icons['ur'])
tmpText = tmpText.replace('{{Lheader}}', str_header1).replace('{{Rheader}}', str_header2)
tmpText = tmpText.replace('{{Lbody}}', str_box1).replace('{{Rbody}}', str_box2)
outFile.write(tmpText)
# lower row of info boxes
tmpText = templateInfoBox.replace('{{Licon}}', icons['ll']).replace('{{Ricon}}', icons['lr'])
tmpText = tmpText.replace('{{Lheader}}', str_header3).replace('{{Rheader}}', str_header4)
tmpText = tmpText.replace('{{Lbody}}', str_box3).replace('{{Rbody}}', str_box4)
outFile.write(tmpText)
outFile.write('\n{{end}}\n')
else:
# if not, it is only the base language
# upper row of info boxes
tmpText = templateInfoBox.replace('{{Licon}}', icons['ul']).replace('{{Ricon}}', icons['ur'])
tmpText = tmpText.replace('{{Lheader}}', str_header1).replace('{{Rheader}}', str_header2)
tmpText = tmpText.replace('{{Lbody}}', str_box1).replace('{{Rbody}}', str_box2)
outFile.write(tmpText)
# lower row of info boxes
tmpText = templateInfoBox.replace('{{Licon}}', icons['ll']).replace('{{Ricon}}', icons['lr'])
tmpText = tmpText.replace('{{Lheader}}', str_header3).replace('{{Rheader}}', str_header4)
tmpText = tmpText.replace('{{Lbody}}', str_box3).replace('{{Rbody}}', str_box4)
outFile.write(tmpText)
outFile.write(templateFooter)
outFile.close()