script and README #4
20
README.md
20
README.md
|
@ -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
199
generate_home_tmpl.py
Normal 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()
|
Loading…
Reference in a new issue