forked from friendica/git.friendi.ca
Merge branch 'master' of tobias/git.friendi.ca into master
This commit is contained in:
commit
02ff15c837
20
README.md
20
README.md
|
@ -1,8 +1,26 @@
|
||||||
# Custom files for git.friendi.ca
|
# Custom files for git.friendi.ca
|
||||||
|
|
||||||
These files are the cutsom 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
|
||||||
|
|
||||||
Translation of the strings can be done at [Transifex](https://www.transifex.com/Friendica/friendica/) with the rest of the project resources.
|
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