Merge branch 'master' of https://github.com/roe-dl/weewx into i18n

This commit is contained in:
Tom Keffer
2021-05-02 10:51:59 -07:00
23 changed files with 1284 additions and 201 deletions

View File

@@ -90,7 +90,8 @@ default_search_list = [
"weewx.cheetahgenerator.Stats",
"weewx.cheetahgenerator.UnitInfo",
"weewx.cheetahgenerator.Extras",
"weewx.cheetahgenerator.JSONHelpers"]
"weewx.cheetahgenerator.JSONHelpers",
"weewx.gettext.Gettext"]
# =============================================================================
@@ -149,7 +150,7 @@ class CheetahGenerator(weewx.reportengine.ReportGenerator):
self.initExtensions(gen_dict[section_name])
# Generate any templates in the given dictionary:
ngen = self.generate(gen_dict[section_name], self.gen_ts)
ngen = self.generate(gen_dict[section_name], section_name, self.gen_ts)
self.teardown()
@@ -198,7 +199,7 @@ class CheetahGenerator(weewx.reportengine.ReportGenerator):
while len(self.search_list_objs):
del self.search_list_objs[-1]
def generate(self, section, gen_ts):
def generate(self, section, section_name, gen_ts):
"""Generate one or more reports for the indicated section. Each
section in a period is a report. A report has one or more templates.
@@ -219,7 +220,7 @@ class CheetahGenerator(weewx.reportengine.ReportGenerator):
if subsection in CheetahGenerator.generator_dict:
section[subsection]['summarize_by'] = subsection
# Call recursively, to generate any templates in this subsection
ngen += self.generate(section[subsection], gen_ts)
ngen += self.generate(section[subsection], subsection, gen_ts)
# We have finished recursively processing any subsections in this
# section. Time to do the section itself. If there is no option
@@ -308,7 +309,7 @@ class CheetahGenerator(weewx.reportengine.ReportGenerator):
pass
searchList = self._getSearchList(encoding, timespan,
default_binding)
default_binding, section_name)
tmpname = _fullname + '.tmp'
try:
@@ -369,14 +370,15 @@ class CheetahGenerator(weewx.reportengine.ReportGenerator):
return ngen
def _getSearchList(self, encoding, timespan, default_binding):
def _getSearchList(self, encoding, timespan, default_binding, section_name):
"""Get the complete search list to be used by Cheetah."""
# Get the basic search list
timespan_start_tt = time.localtime(timespan.start)
searchList = [{'month_name' : time.strftime("%b", timespan_start_tt),
'year_name' : timespan_start_tt[0],
'encoding' : encoding},
'encoding' : encoding,
'page' : section_name},
self.outputted_dict]
# Bind to the default_binding:

142
bin/weewx/gettext.py Normal file
View File

@@ -0,0 +1,142 @@
# Simple localization for WeeWX
# Copyright (C) 2021 Johanna Karen Roedenbeck
# See the file LICENSE.txt for your full rights.
"""
provides tag $gettext(key, page)
Language dependent texts are stored in special localization files.
The are merged into skin_dict in reportengine.py according to the
language the user chooses in weewx.conf for the given report.
Different reports can be in different languages.
The file defines language dependent label texts as well as other
texts used in skins.
The values provided by $gettext(key, page) are found in the file
in the [Texts] section. Subsections in the [Texts] section can
provide special texts for certain templates. To get values from
subsections $gettext() is called with special tag $page for the
parameter page. That is especially useful in include files that
are included in multiple templates.
Examples:
Assume the localization file to be:
[Texts]
Key1 = Text1
[[index]]
Title = Text2
[[othertemplate]]
Title = Text3
With that file is:
$gettext("Key1") ==> Text1
$gettext("Title",$page) ==> is Text2 if included in template "index"
and Text3 if included in template
"othertemplate"
$gettext(page=$page).Title ==> same as before
You can use "speaking" key names. If they contain whitespace they need
to be enclosed in quotes in the localization file
If the value contains commas you must enclose it in single or double
quotes. Otherwise an array instead of a string is returned.
"""
from six.moves import collections_abc
from weewx.cheetahgenerator import SearchList
from weeutil.weeutil import KeyDict
import weeutil.config
# Test for new-style weewx v4 logging by trying to import weeutil.logger
import weeutil.logger
import logging
log = logging.getLogger(__name__)
class Gettext(SearchList):
def get_extension_list(self,timespan,db_lookup):
def locale_label(key='',page=''):
""" $gettext()
key: key to look up for
page: section name
"""
_text_dict = self.generator.skin_dict.get('Texts',{})
# get the appropriate section for page if defined
# Note: no hierarchy here
if page:
if page not in _text_dict:
log.error("could not find section [Texts][[%s]] for report %s" % (page,self.generator.skin_dict.get('REPORT_NAME','unknown')))
# Note: no 'else:' here, because we need the empty dict
# page is specified --> get subsection "page"
_text_dict = _text_dict.get(page,{})
# if key is not empty, get the value for key
if key:
# return the value for key
# if key not in _text_dict return key instead
return KeyDict(_text_dict)[key]
# if key is empty but page is not return further class instance
if page:
_page_dict = weeutil.config.config_from_str('')
#merge_dict = self.generator.skin_dict.get('Labels',{}).get('Generic',{})
#if merge_dict:
# weeutil.config.merge_config(_page_dict,merge_dict)
merge_dict = Gettext._get_cheetah_dict(self.generator.skin_dict.get('CheetahGenerator',{}),page)
if merge_dict:
weeutil.config.merge_config(_page_dict,merge_dict)
weeutil.config.merge_config(_page_dict,_text_dict)
return _page_dict
# if key as well as page are empty
return ParallelDict(_text_dict)
return [{'gettext':locale_label}]
@staticmethod
def _get_cheetah_dict(cheetah_dict,page):
""" find section page in cheetah_dict recursively """
for section in cheetah_dict.sections:
subsection = Gettext._get_cheetah_dict(cheetah_dict[section],page)
if subsection is not None:
return subsection
if page in cheetah_dict:
return cheetah_dict[page]
return None
class ParallelDict(collections_abc.Mapping):
def __init__(self, source):
self.source = source
def __getitem__(self, key):
try:
return self.source[key]
except KeyError:
return key
def __len__(self):
return self.source.__len__()
def __iter__(self):
for key in self.source:
yield key

View File

@@ -254,6 +254,72 @@ class StdReportEngine(threading.Thread):
for scalar in self.config_dict['StdReport'].scalars:
skin_dict[scalar] = self.config_dict['StdReport'][scalar]
#######################################################################
# internationalization support
# The key 'lang' defines a language code like 'en' or 'de'. It is
# used as a file name for a language file that is located in the
# 'lang' subdirectory of the skin directory.
# get the language option if defined
# (As config_dict is not merged into skin_dict so far,
# skin_dict['lang'] has not the final value here. We
# have to take config_dict into account, too.)
lang_config = self.config_dict['StdReport'][report].get('lang',skin_dict.get('lang',None))
if lang_config:
# Now add the options in the report's localization file. Start by figuring where it is located.
lang_config_path = os.path.join(
self.config_dict['WEEWX_ROOT'],
self.config_dict['StdReport']['SKIN_ROOT'],
self.config_dict['StdReport'][report].get('skin', ''),
'lang',
lang_config+'.conf')
# Now retrieve the language dictionary for the skin. Wrap it in a try block in case we fail. It is ok if
# there is no file - everything for a skin might be defined in the weewx configuration.
try:
merge_dict = configobj.ConfigObj(lang_config_path, file_error=True, encoding='utf-8')
log.debug("Found localization file %s for report '%s'", lang_config_path, report)
# make sure 'Texts' is present and a dict (section)
if not isinstance(merge_dict.get('Texts',None),dict):
if 'Texts' in merge_dict:
log.error("'Texts' is not a section in '%s'" % lang_config_path)
merge_dict['Texts']={}
# set language code for $gettext.lang
merge_dict['Texts']['lang'] = os.path.basename(lang_config_path).split('.')[0]
# Merge the skin config file in:
weeutil.config.merge_config(skin_dict, merge_dict)
if self.first_run:
log.info("Using localization file %s for report '%s'" %
(lang_config_path, report))
except IOError as e:
log.debug("Cannot read localization file %s for report '%s': %s",
lang_config_path, report, e)
except SyntaxError as e:
log.error("Failed to read localization file %s for report '%s': %s",
lang_config_path, report, e)
raise
# See if the user wants this report based on another unit system than US.
# The value can be US, METRIC, or METRICWX.
# (As config_dict is not merged into skin_dict so far,
# skin_dict['units_base'] has not the final value here. We
# have to take config_dict into account, too.)
report_units_base = self.config_dict['StdReport'][report].get('units_base',skin_dict.get('units_base',None))
if report_units_base:
# Get the chosen unit system out of units.py. Copy it to prevent
# the original from being changed. Merge it into skin_dict.
try:
merge_dict = weewx.units.std_groups[weewx.units.unit_constants[report_units_base]].copy()
weeutil.config.merge_config(skin_dict, {'Units':{'Groups':merge_dict}})
except (SyntaxError,TypeError,IndexError,ValueError,IOError) as e:
log.error("error merging unit system '%s' for report '%s'" % (report_units_base,report))
#######################################################################
# Finally, inject any overrides for this specific report. Because this is the last merge, it will have the
# final say.
weeutil.config.merge_config(skin_dict, self.config_dict['StdReport'][report])

View File

@@ -443,7 +443,8 @@ Version: 4.6
<p>
Each report has a <em>skin</em> associated with it. For most reports, the relationship with the skin is an
obvious one: it contains the templates, any auxiliary files such as background GIFs or CSS style sheets, and
obvious one: it contains the templates, any auxiliary files such as background
GIFs or CSS style sheets, files with localization data, and
a <em>skin configuration file</em>, <span class="code">skin.conf</span>. If you will, the skin controls the
<em>look and feel </em>of the report. Note that more than one report can use the same skin. For example, you
might want to run a report that uses US Customary units, then run another report against the same skin, but
@@ -807,6 +808,16 @@ db_manager.getSql("SELECT SUM(rain) FROM %s "\
<td class="code">[[[Labels]]] / [[[[Generic]]]]</td>
<td>Highest precedence. Has the final say.</td>
</tr>
<tr>
<td class="code">skins/<span
class="symcode">report_name</span>/ lang/<span
class="symcode">language_code</span>.conf</td>
<td></td>
<td>Affects only the report <span class="symcode">report_name</span>.</td>
<td class="code">[Labels] / [[Generic]]</td>
<td>Internationalization support. Preferably
supplied by the skin author.</td>
</tr>
<tr>
<td class="code">weewx.conf</td>
<td class="code"><a href="#change_defaults">[StdReport] / [[Defaults]]</a></td>
@@ -884,6 +895,46 @@ db_manager.getSql("SELECT SUM(rain) FROM %s "\
wants to use the string <span class="code">Exterior Temperature</span>, instead of <span class="code">Outside Temperature</span>
for the label for <span class="code">outTemp</span>. The file includes no definition for <span class="code">inTemp</span>.
</p>
<p>
Now suppose the skin author took care of internationalization
and provided language files. In this case s/he would not have
set the label in <span class="code">skin.conf</span> but in
a language file, for English in
<span class="code">lang/en.conf</span>, for german in
<span class="code">lang/de.conf</span> etc.
</p>
<p>
<span class="code">lang/en.conf</span> would contain
what was defined in <span class="code">skin.conf</span>
before:
</p>
<pre class="tty">
...
[Labels]
...
[[Generic]]
...
outTemp = Exterior Temperature
</pre>
<p>
<span class="code">lang/de.conf</span> would contain:
</p>
<pre class="tty">
...
[Labels]
...
[[Generic]]
...
outTemp = Außentemperatur
inTemp = Innentemperatur
</pre>
<p>
The user sets the language by the optional
<span class="code">lang</span> option in
<span class="code">weewx.conf</span>.
</p>
<p>
Finally, for purposes of illustrating precedence, suppose the <span class="code">[StdReport]</span> section
of <span class="code">weewx.conf</span> contains this:
@@ -904,6 +955,10 @@ db_manager.getSql("SELECT SUM(rain) FROM %s "\
[[[Labels]]]
[[[[Generic]]]]
outTemp = Barn Temperature
[[LifeC]]
skin = Life
lang = de
</pre>
<p>
@@ -931,20 +986,31 @@ db_manager.getSql("SELECT SUM(rain) FROM %s "\
<td>Inside Temperature</td>
<td>Barn Temperature</td>
</tr>
<tr>
<td>LifeC</td>
<td>Innentemperatur</td>
<td>Außentemperatur</td>
</tr>
</table>
<p>
Note how the values specified for <span class="code">inTemp</span> are not overridden anywhere, so the value
Note how the values specified for <span class="code">inTemp</span>
are not overridden anywhere, except
<span class="clode">lang/de.conf</span>, so the value
specified in <span class="code">weewx/defaults.py</span>, that is, <span
class="code">Inside Temperature</span>, is used for all reports.</p>
class="code">Inside Temperature</span>, is used for all reports,
except <span class="code">LifeC</span>.</p>
<p>
The value for <span class="code">outTemp</span> is not overridden for report <span class="code">SeasonsA</span>,
so it uses the label specified in <span class="code">weewx/defaults.py</span>, that is, <span class="code">Outside Temperature</span>.
By contrast, for the "Life" reports, a value for <span class="code">outTemp</span>
was specified in the skin so, in the absence of any user override, its value, <span class="code">Exterior
Temperature</span> will be used as the new default. Finally, for the report <span class="code">LifeB</span>,
Temperature</span> will be used as the new default. For the report <span class="code">LifeB</span>,
the user <em>has</em> specified an override for <span class="code">outTemp</span>, so that value,
<span class="code">Barn Temperature</span>, is used.
Finally, for the report <span class="code">LifeC</span>
a language has been set, so the labels are taken from the
specified language file.
</p>
<p>
@@ -1119,7 +1185,40 @@ db_manager.getSql("SELECT SUM(rain) FROM %s "\
</p>
<p>
To accomplish this, we will generate two reports, one using the defaults, the other using overrides to
change the target unit system and the target directory. The section <span class="code">[StdReport]</span>
change the target unit system and the target directory.
</p>
<p>
If you only want to use one of the predefined unit systems
like <span class="code">US</span> or
<span class="code">METRIC</span> you can simply specify
a unit system in the report configuration like this:
</p>
<pre class="tty">
[StdReport]
# Where the skins reside, relative to WEEWX_ROOT
SKIN_ROOT = skins
# Where the generated reports should go, relative to WEEWX_ROOT
HTML_ROOT = public_html
# The database binding indicates which data should be used in reports.
data_binding = wx_binding
<span class="highlight"> [[SeasonsUSReport]]</span>
skin = Seasons
<span class="higlight">units_base = US</span>
enable = true
<span class="highlight"> [[SeasonsMetricReport]]
skin = Seasons
units_base = METRIC
enable = true
HTML_ROOT = public_html/metric</pre>
<p>
If you need individual settings for a lot of units you
can specify the units directly in the report configuration.
In this case the section <span class="code">[StdReport]</span>
will look like this:
</p>
<pre class="tty">
@@ -2962,6 +3061,207 @@ $month.outTemp.series(aggregate_type='max', aggregate_interval='day', time_serie
<a href="https://github.com/weewx/weewx/wiki/Tags-for-series"><em>Tags for series</em></a>.
</p>
<h3>General tags</h3>
<p>
There are some general tags, that do not reflect observation
data but technical data of processing the template files.
You can especially use them in <span class="code">#if</span>
expressions to control how Cheetah processes the template.
</p>
<table class="indent">
<tbody>
<tr class="first_row">
<td>Tag</td>
<td>Description</td>
</tr>
<tr>
<td class="code first_col">$month_name</td>
<td>Name of the month, the file is created for</td>
</tr>
<tr>
<td class="code first_col">$year_name</td>
<td>Year, the file is created for</td>
</tr>
<tr>
<td class="code first_col">$encoding</td>
<td>Character encoding, to which the file is converted
after creation. Possible values are
<span class="code">html_entities</span>,
<span class="code">strict_ascii</span>,
<span class="code">normalized_ascii</span>, and
<span class="code">utf-8</span>.
</td>
</tr>
<tr>
<td class="code first_col">$page</td>
<td>Name of the page that is actually processed.
This is the section name from
<span class="code">skin.conf</span>
where the template is described. You can especially
use it in include files that are included in multiple
templates. So parts of the content defined in the include
file can depend on the template file, for example
header lines. You can also use it together with
<span class="code">$gettext</span> to structure
the language file.</td>
</tr>
<tr>
<td class="code first_col">$gettext.lang</td>
<td>Language code set by the
<span class="code">lang</span> option
for the report. You can use this tag in
<span class="code">#if</span> expressions and
to include language codes where the HTML
specification requires them.
</tr>
<tr>
<td class="code first_col">$gettext(page=$page).template</td>
<td>
File name of the template actually processed
</td>
</tr>
</tbody>
</table>
<h3 id="Tag_$gettext">
Internationalization support with
<span class="code">$gettext</span>
</h3>
<p>
Web pages and other files to be created do not only contain
observation values and their labels but also static text.
The <span class="code">$gettext</span> tag provides
internationalization support for those static texts.
To support internationalization do not write static
text into to template or include files but use
<span class="code">$gettext</span> there to define it.
</p>
<p>
Suppose you write a skin called
"<span class="code">YourSkin</span>"
and
you want to have a head line in there, that
is "Current Conditions" in English, but "aktuelle Werte"
in german, "Conditions actuelles" in french etc. Then
the template file could contain:
</p>
<pre class="tty">...
&lt;h1&gt;$gettext("Current Conditions")&lt;/h1&gt;
...</pre>
<p>
The section of <span class="code">weewx.conf</span>
configuring your skin could now look like this:
</p>
<pre class="tty">...
[StdReport]
...
[[YourSkinReport]]
skin = YourSkin
lang = fr
...</pre>
<p>
With <span class="code">lang = fr</span> the report
is in french. To get it in English, replace the language
code <span class="code">fr</span> by the code for English
<span class="code">en</span>. And to get it in german
use <span class="code">de</span>.
</p>
<p>
To make that work a language file has to be created for
each language supported. The language files reside in
the <span class="code">lang</span> subdirectory of the
skin directory that is defined by the
<span class="code">skin</span> option. The file name
of the language file is the language code appended
by <span class="code">.conf</span>, for example
<span class="code">en.conf</span>,
<span class="code">de.conf</span>, or
<span class="code">fr.conf</span>.
</p>
<p>
The language file has the same layout as
<span class="code">skin.conf</span>, i.e.
you can put language specific versions of the labels there.
Additionally a section <span class="code">[Texts]</span>
can be defined to hold the static texts used in the skin.
For the example above the language files would contain
the following:
</p>
<p class="code">en.conf</p>
<pre class="tty">...
[Texts]
"Current Conditions" = Current Conditions
...</pre>
<p class="code">de.conf</p>
<pre class="tty">...
[Texts]
"Current Conditions" = Aktuelle Werte
...</pre>
<p class="code">fr.conf</p>
<pre class="tty">...
[Texts]
"Current Conditions" = Conditions actuelles
</pre>
<p>
While it is not technically necessary we recommend to use
the whole English text for key. The template is easier to
read then. And it is easier for the person who translates
the texts if the original English version of the text is
found on the left side. But there are cases when that is
not possible, and then you can use any string you find
reasonable enough to describe the entry.
</p>
<p>
See the <span class="symcode">SKIN_ROOT</span><span class="code">/Seasons/lang</span>
subdirectory for examples of language files.
</p>
<p>
If your skin is big and there are lots of texts to define
you can structure the <span class="code">[Texts]</span>
section by subsections. Each template can have its own
subsection. The subsections need to be called identically
to the respective sections in <span class="code">skin.conf</span>.
<p/p>
<p>
Assuming you have a template section called
<span class="code">[[[index]]]</span> and another
section called <span class="code">[[[othertemplate]]]</span>,
then the language files could look like this:
</p>
<pre class="tty">...
[Texts]
...some general texts here...
[[index]]
...some texts for template index here, for example
Key = Some text
[[othertemplate]]
...some texts for template othertemplate here, for example
Key = Some other text</pre>
<p>
To refer to these template specific texts add
<span class="code">$page</span> as parameter to
<span class="code">$gettext()</span>. For example:
</p>
<pre class="tty">...
$gettext("Key",$page)
...</pre>
<p>
If template "index" is processed, the entry "Key" in
subsection <span class="code">[[index]]</span> is
used, and the value is "Some text".
If template "othertemplate" is processed, the
entry "Key" in subsection
<span class="code">[[othertemplate]]</span>
is used, and the value is "Some other text".
You can place this tag in an include file
that is called by both "index" and "othertemplate",
and the value is chosen from the appropriate subsection.
</p>
<h2>Almanac</h2>
<p>
@@ -4179,10 +4479,49 @@ class MyStats(SearchList): # 1
<h1 id="localization">Localization</h1>
<p>
This section is provides suggestions for localization, including translation to different languages and
This section provides suggestions for localization,
including translation to different languages and
display of data in formats specific to a locale.
</p>
<h2>If localization is already done</h2>
<p>
First look whether the skin already came with a localization
for your language. If there is a
<span class="code">lang</span> subdirectory in the skin
directory, look into it. There you find a file for each
language this skin is already localized to. If your
language is there, all you need to do is to select it
in <span class="code">weewx.conf</span>:
</p>
<pre class="tty">...
[StdReport]
...
[[TheSkin]]
skin = skin_directory
<span class="highlight">lang = language_code</span>
...</pre>
<h2>If only your language is missing</h2>
<p>
If the <span class="code">lang</span> subdirectory
is present in the skin directory the skin is
probably prepared already for localization.
The only thing to do then is translating.
To do so, copy the file
<span class="code">en.conf</span> and name it
according to the language code of your language.
Then translate all the strings on the right
side of the equal signs to your language.
The skin author may be interested in your
language file to ship it together with the
skin for the use of other users.
Last set the language code in
<span class="code">weewx.conf</span>
as described in the previous section.
</p>
<h2>How to localize a single report</h2>
<p>
@@ -4191,15 +4530,37 @@ class MyStats(SearchList): # 1
formats and language.
</p>
<h3>Create the language file</h3>
<p>
Create a subdirectory called <span class="code">lang</span>
in the skin directory.
Then create a file named by the language code with the
suffix <span class="code">.conf</span>. For example, if
you want to translate to spanish, name the file
<span class="code">es.conf</span>.
The next step is
to make the templates language-aware as described in the
following section.
</p>
<h3>Translate the templates</h3>
<p>
In every HTML template (these typically have a file suffix of <span class="code">.html.tmpl</span>) change
the HTML "lang" attribute to the target language. For example, for Spanish use <span class="code">es</span>:
Open the template file and the language file in different
editor windows. It is much easier if you can change both
files simultaneously.
</p>
<p>
In every HTML template (these typically have a file suffix of
<span class="code">.html.tmpl</span>) change
the HTML "lang" attribute to a configurable value.
</p>
<pre class="tty">
&lt;!DOCTYPE html&gt;
&lt;html lang="<span class="highlight">es</span>"&gt;
&lt;html lang="<span class="highlight">$gettext.lang</span>"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
...
@@ -4232,12 +4593,26 @@ class MyStats(SearchList): # 1
<pre class="tty">
&lt;div id='current_widget' class="widget"&gt;
&lt;div class="widget_title"&gt;
<span class="highlight">Conditions Actuelle</span>
<span class="highlight">$gettext("Current Conditions")</span>
&lt;a class="widget_control"
onclick="toggle_widget('current')"&gt;&amp;diams;&lt;/a&gt;
&lt;/div&gt;
</pre>
<p>
In the language file start a
<span class="code">[Texts]</span> section and place the
translation there like:
</p>
<pre class="tty">...
[Texts]
...
"Current Conditions" = Conditions Actuelles
...</pre>
<p>
Repeat that for all strings you find. Make sure not
to replace HTML tags and HTML options.
</p>
<h3>Translate labels and modify local options</h3>
<p>
@@ -4354,13 +4729,21 @@ class MyStats(SearchList): # 1
locales? This example shows how to translate the <em>Seasons</em> skin for multiple languages.
</p>
<p>
Create a directory for each language. Each directory contains template files and a skin configuration file.
Any text in each template file should be in the target language. Ensure that each HTML template file has the
<span class="code">lang</span> set properly.
Create a subdirectory called
<span class="code">lang</span> in the skin directory.
The language files containing the language dependent
information go there. Start creating a language file
for the primary language and save it to the
<span class="code">lang</span> directory. The name
of the file consists of the language code of the
target language and the suffix
<span class="code">.conf</span>. Later on you can
create language files for each language you want
to support based on that file.
</p>
<p>
Translate observation names and other labels, and put them into the skin configuration files. There should
be one configuration file for each language.
Translate observation names and other labels, and put them
into the created language file.
</p>
<p>
Ensure that any locale-specific formatting is specified properly. For example, consider the <span
@@ -4372,19 +4755,27 @@ class MyStats(SearchList): # 1
whatever locale is set in the environment in which WeeWX is running.
</p>
<p>
The result will be a directory of templates and configurations, with one directory for each
Static texts are localized using the
<span class="code">$gettext(</span><span class="symcode">"original text"</span><span class="code">)</span> tag.
Create a section <span class="code">[Texts]</span>
in the language file and place a line
</p>
<pre class="tty">"original text" = translated text</pre>
<p>
there in each language file. In the template file you refer
to those texts by
</p>
<pre class="tty">$gettext("original text")</pre>
<p>
According to the language setting of the report the tag
stands for the text in the appropriate language.
</p>
<p>
The result will be a directory of language files
with one file for each
language/localization.
</p>
<pre class="tty">
skins/Seasons/
skins/Seasons/en/skin.conf
skins/Seasons/en/index.html.tmpl
skins/Seasons/es/skin.conf
skins/Seasons/es/index.html.tmpl
skins/Seasons/de/skin.conf
skins/Seasons/de/index.html.tmpl
skins/Seasons/fr/skin.conf
skins/Seasons/fr/index.html.tmpl</pre>
<p>
Users will then create each report in the WeeWX configuration file.
@@ -4392,16 +4783,20 @@ skins/Seasons/fr/index.html.tmpl</pre>
<pre class="tty">
[StdReport]
[[Seasons_en]]
skin = Seasons/en
skin = Seasons
lang = en
HTML_ROOT = public_html/en
[[Seasons_es]]
skin = Seasons/es
skin = Seasons
lang = es
HTML_ROOT = public_html/es
[[Seasons_de]]
skin = Seasons/de
skin = Seasons
lang = de
HTML_ROOT = public_html/de
[[Seasons_fr]]
skin = Seasons/fr
skin = Seasons
lang = fr
HTML_ROOT = public_html/fr</pre>
<p>
The result is multiple reports, each in a different language and localization, independent of the locale of
@@ -5696,7 +6091,23 @@ xstats/bin/user/xstats.py</pre>
<p>
This section contains the options available in the skin configuration file, <span
class="code">skin.conf</span>.
class="code">skin.conf</span>. The same options apply to the
language files found in the subdirectory
<span class="code">lang</span>, like
<span class="code">lang/en.conf for English</span>.
</p>
<p>
We recommend to put
<ul>
<li>
options that control the behavior of the skin into
<span class="code">skin.conf</span> and
</li>
<li>
language dependent labels and texts into the
language files.
</li>
</ul>
</p>
<p>
@@ -6104,10 +6515,48 @@ growing_base = 50.0, degree_F</pre>
class="code">time_delta</span> will be accepted. Default is 300 seconds.
</p>
<h2 class="config_section" id="texts">[Texts]</h2>
<p>
This section applies to language files only.
</p>
<p>
The section <span class="code">[Texts]</span> holds
static texts that are used in the templates.
Generally there are multiple language files, each file
for one language and named by the language code
defined in <a
href="https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes"
target="_blank">ISO&nbsp;639-1</a>.
The entries
give the translation of the texts to the target language, like
</p>
<pre class="tty">"English text" = same text in the target language</pre>
<p>
or define texts by keys that can be refereced within the template.
</p>
<pre class="tty">"Key" = some text to display</pre>
<p>
To use the English text for the key is recommended, because
the template is easier to read then and while translating
you see the original English text on the left side.
</p>
<p class="warning">
<strong>Note!</strong><br/>
Strings that include commas must be included in single or
double quotes.
</p>
<p>
There may be subsections, named like the template
subsections in the
<span class="code">[CheetahGenerator]</span> section of
<span class="code">skin.conf</span>. The entries defined
in such subsections apply to the respective template only.
<h2 id="CheetahGenerator">[CheetahGenerator]</h2>
<p>This section contains the options for the Cheetah generator.</p>
<p>This section contains the options for the Cheetah generator.
It applies to <span class="code">skin.conf</span> only.</p>
<p class="config_option">search_list</p>

View File

@@ -2273,8 +2273,11 @@ longitude = -77.0366</pre>
<p>
These are the four reports that actually generate HTML files and plots. They all ship in the standard WeeWX
distribution. They all use US Customary units by default, but this can be changed by editing section <a
href="#Section_Defaults"><span class="code">[Defaults]</span></a>.
distribution. They all use US Customary units by default, but this can be changed
by setting the option <span
class="code">units_base</span> or
by editing section <a href="#Section_Defaults"><span
class="code">[StdReport][[Defaults]]</span></a>.
</p>
<p>They all have the following options in common.</p>
@@ -2284,6 +2287,55 @@ longitude = -77.0366</pre>
the directory should be any templates used by the skin and a skin configuration file, <span class="code">skin.conf</span>.
</p>
<p class="config_important">lang</p>
<p>
Which language to display the skin.
The value to this option is a two-character language code as defined in <a
href="https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes"
target="_blank">ISO&nbsp;639-1</a>.
It defines the language the skin shall be displayed in.
For each language, that a certain skin can display, an appropriate
language file resides in the
<span class="code">lang</span> subdirectory of the
skin directory. It is named by the language code, appended
by <span class="code">.conf</span>, for example
<span class="code">en.conf</span> for English.
If there is no file for your language,
copy <span class="code">en.conf</span> and translate
the texts on the right side of the equal signs to the
language you want to use. It is important that you name
the file according to the list in ISO&nbsp;639-1.
</p>
<p><span class="config_option">units_base</span></p>
<p>
Which unit system to use with the skin. That can be
<span class="code">US</span>,
<span class="code">METRIC</span>, or
<span class="code">METRICWX</span>.
If the option is not set, the units set in the
<span class="code">[StdReport][[Defaults]]</span>
section are used. If no defaults are
set, <span class="code">US</span> is the default.
See the section "<a
href="customizing.htm#Changing_the_unit_system">Changing
the unit system</a>" in the "<a
href="customizing.htm">Customization Guide</a>"
for more details.
The difference between <span class="code">METRICDE</span>
and the other metric unit systems is that it uses
<span class="code">mm</span> for rain and
<span class="code">km/h</span> for wind.
Settings in the section
<span class="code">[[[Units]]][[[[Groups]]]]</span>
overwrite the unit settings resulting from this option
for individual observation types. See "<a
href="customizing.htm#how_to_change_units">How to
change units</a>" in the "<a
href="customizing.htm">Customization Guide</a>"
for more details.
</p>
<p class="config_important">enable</p>
<p>
Set to <span class="code">true</span> to enable the processing of this skin. Set to <span
@@ -2422,6 +2474,28 @@ longitude = -77.0366</pre>
deleted on the remote server. Valid values are 1 to enable and 0 to disable. Required. Default is 0.
</p>
<h3 class="config_section" id="Section_Defaults">[[Defaults]]</h3>
<p>
This section defines default values for all skins. You can set:
<ul>
<li>units to be used with observation types</li>
<li>number and time formats</li>
<li>labels</li>
<li>calculation options for some derived values</li>
</ul>
See the <a href="customizing.htm">Customization Guide</a>
for more details.
</p>
<p>
If the skin you use comes with internationalization
support and you set a language by the
<span class="code">lang</span> option, the settings
resulting from this option overwrite the settings in
the <span class="code">[[Defaults]]</span> section.
</p>
<h2 class="config_section" id="StdConvert">[StdConvert]</h2>
<p>This section is for configuring the <span class="code">StdConvert</span> service. This service acts as a
@@ -3081,12 +3155,6 @@ longitude = -77.0366</pre>
Default is <span class="code">INNODB</span>.
</p>
<h2 class="config_section" id="Section_Defaults">[Defaults]</h2>
<p>
This section covers a suite of default values, which control things such as which unit system should be
used in reports, what label to be used for an observation type, and how it should be formatted.
</p>
<h2 class="config_section">[Engine]</h2>
<p>

View File

@@ -6,7 +6,7 @@
<div id='about_widget' class="widget">
<div class="widget_title">
About this weather station
$gettext["About"]
<a class="widget_control"
onclick="toggle_widget('about')">&diams;</a>
</div>
@@ -17,15 +17,15 @@
<td class="data">$station.hardware</td>
</tr>
<tr>
<td class="label">Latitude</td>
<td class="label">$gettext["Latitude"]</td>
<td class="data">$station.latitude[0]&deg; $station.latitude[1]' $station.latitude[2]</td>
</tr>
<tr>
<td class="label">Longitude</td>
<td class="label">$gettext["Longitude"]</td>
<td class="data">$station.longitude[0]&deg; $station.longitude[1]' $station.longitude[2]</td>
</tr>
<tr>
<td class="label">Altitude</td>
<td class="label">$gettext["GeoAltitude"]</td>
<td class="data">$station.altitude</td>
</tr>
<tr>

View File

@@ -3,7 +3,7 @@
#errorCatcher Echo
#encoding UTF-8
<!DOCTYPE html>
<html lang="en">
<html lang="$gettext.lang">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>$station.location Celestial Details</title>
@@ -31,7 +31,7 @@
#include "titlebar.inc"
<div id="contents">
<p><a href="index.html">&#10096; Current Conditions</a></p>
<p><a href="index.html">&#10096; $gettext["Current Conditions"]</a></p>
<div id="widget_group">
#include "celestial.inc"

View File

@@ -49,131 +49,131 @@
<div id="celestial_widget" class="widget">
<div class="widget_title">
Celestial
$gettext[$page]["Title"]
</div>
<div class="widget_contents">
#if $almanac.hasExtras
<div id="celestial_details">
<div class="celestial_body">
<table class="celestial">
<tr><th>&#9728; Sun</th><th></th></tr>
<tr><th>&#9728; $gettext[$page]["Sun"]</th><th></th></tr>
<tr>
<td class="label">Start civil twilight</td>
<td class="label">$gettext[$page]["Start civil twilight"]</td>
<td class="data">$almanac(horizon=-6).sun(use_center=1).rise</td>
</tr>
<tr>
<td class="label">Rise</td>
<td class="label">$gettext[$page]["Rise"]</td>
<td class="data">$almanac.sun.rise.format(None_string=$sun_None)</td>
</tr>
<tr>
<td class="label">Transit</td>
<td class="label">$gettext[$page]["Transit"]</td>
<td class="data">$almanac.sun.transit</td>
</tr>
<tr>
<td class="label">Set</td>
<td class="label">$gettext[$page]["Set"]</td>
<td class="data">$almanac.sun.set.format(None_string=$sun_None)</td>
</tr>
<tr>
<td class="label">End civil twilight</td>
<td class="label">$gettext[$page]["End civil twilight"]</td>
<td class="data">$almanac(horizon=-6).sun(use_center=1).set</td>
</tr>
<tr>
<td class="label">Azimuth</td>
<td class="label">$gettext[$page]["Azimuth"]</td>
<td class="data">$("%.1f&deg;" % $almanac.sun.az)</td>
</tr>
<tr>
<td class="label">Altitude</td>
<td class="label">$gettext[$page]["AstroAltitude"]</td>
<td class="data">$("%.1f&deg;" % $sun_altitude)</td>
</tr>
<tr>
<td class="label">Right ascension</td>
<td class="label">$gettext[$page]["Right ascension"]</td>
<td class="data">$("%.1f&deg;" % $almanac.sun.ra)</td>
</tr>
<tr>
<td class="label">Declination</td>
<td class="label">$gettext[$page]["Declination"]</td>
<td class="data">$("%.1f&deg;" % $almanac.sun.dec)</td>
</tr>
#if $almanac.next_equinox.raw < $almanac.next_solstice.raw
## The equinox is before the solstice. Display them in order.
<tr>
<td class="label">Equinox</td>
<td class="label">$gettext[$page]["Equinox"]</td>
<td class="data">$almanac.next_equinox</td>
</tr>
<tr>
<td class="label">Solstice</td>
<td class="label">$gettext[$page]["Solstice"]</td>
<td class="data">$almanac.next_solstice</td>
</tr>
#else
## The solstice is before the equinox. Display them in order.
<tr>
<td class="label">Solstice</td>
<td class="label">$gettext[$page]["Solstice"]</td>
<td class="data">$almanac.next_solstice</td>
</tr>
<tr>
<td class="label">Equinox</td>
<td class="label">$gettext[$page]["Equinox"]</td>
<td class="data">$almanac.next_equinox</td>
</tr>
#end if
<tr>
<td class="label">Total daylight</td>
<td class="label">$gettext[$page]["Daylight"]</td>
<td class="data">$daylight_str</td>
</tr>
</table>
</div>
<div class="celestial_body">
<table class="celestial">
<tr><th>&#9789; Moon</th><th></th></tr>
<tr><th>&#9789; $gettext[$page]["Moon"]</th><th></th></tr>
<tr><td class="label">&nbsp;</td><td class="data">&nbsp;</td></tr>
<tr>
<td class="label">Rise</td>
<td class="label">$gettext[$page]["Rise"]</td>
<td class="data">$almanac.moon.rise</td>
</tr>
<tr>
<td class="label">Transit</td>
<td class="label">$gettext[$page]["Transit"]</td>
<td class="data">$almanac.moon.transit</td>
</tr>
<tr>
<td class="label">Set</td>
<td class="label">$gettext[$page]["Set"]</td>
<td class="data">$almanac.moon.set</td>
</tr>
<tr><td class="label">&nbsp;</td><td class="data">&nbsp;</td></tr>
<tr>
<td class="label">Azimuth</td>
<td class="label">$gettext[$page]["Azimuth"]</td>
<td class="data">$("%.1f&deg;" % $almanac.moon.az)</td>
</tr>
<tr>
<td class="label">Altitude</td>
<td class="label">$gettext[$page]["AstroAltitude"]</td>
<td class="data">$("%.1f&deg;" % $almanac.moon.alt)</td>
</tr>
<tr>
<td class="label">Right ascension</td>
<td class="label">$gettext[$page]["Right ascension"]</td>
<td class="data">$("%.1f&deg;" % $almanac.moon.ra)</td>
</tr>
<tr>
<td class="label">Declination</td>
<td class="label">$gettext[$page]["Declination"]</td>
<td class="data">$("%.1f&deg;" % $almanac.moon.dec)</td>
</tr>
#if $almanac.next_full_moon.raw < $almanac.next_new_moon.raw
<tr>
<td class="label">Full moon</td>
<td class="label">$gettext[$page]["Full moon"]</td>
<td class="data">$almanac.next_full_moon</td>
</tr>
<tr>
<td class="label">New moon</td>
<td class="label">$gettext[$page]["New moon"]</td>
<td class="data">$almanac.next_new_moon</td>
</tr>
#else
<tr>
<td class="label">New moon</td>
<td class="label">$gettext[$page]["New moon"]</td>
<td class="data">$almanac.next_new_moon</td>
</tr>
<tr>
<td class="label">Full moon</td>
<td class="label">$gettext[$page]["Full moon"]</td>
<td class="data">$almanac.next_full_moon</td>
</tr>
#end if
<tr>
<td class="label">Phase</td>
<td class="label">$gettext[$page]["Phase"]</td>
<td class="data">$almanac.moon_phase<br/>
$almanac.moon_fullness% full</td>
</tr>

View File

@@ -6,7 +6,7 @@
<div id='current_widget' class="widget">
<div class="widget_title">
Current Conditions
$gettext["Current Conditions"]
<a class="widget_control"
onclick="toggle_widget('current')">&diams;</a>
</div>

View File

@@ -8,7 +8,7 @@
<div id='hilo_widget' class="widget">
<div class="widget_title">
<a href="statistics.html">High/Low</a>
<a href="statistics.html">$gettext["HiLo"]</a>
<a class="widget_control"
onclick="toggle_widget('hilo')">&diams;</a>
</div>
@@ -18,14 +18,15 @@
<tbody>
<tr>
<td></td>
<th>&nbsp;<br/>Today</th>
<th class="hilo_week">&nbsp;<br/>Week</th>
<th class="hilo_month">&nbsp;<br/>Month</th>
<th>&nbsp;<br/>$gettext["Today"]</th>
<th class="hilo_week">&nbsp;<br/>$gettext["Week"]</th>
<th class="hilo_month">&nbsp;<br/>$gettext["Month"]</th>
<th class="hilo_year">
<a onclick="toggle_rainyear()">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>Year</a>
<a
onclick="toggle_rainyear()">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>$gettext["Year"]</a>
</th>
<th class="hilo_rainyear">
<a onclick="toggle_rainyear()">Rain<br/>Year</a>
<a onclick="toggle_rainyear()">$gettext["Rainyear1"]<br/>$gettext["Rainyear2"]</a>
</th>
<td></td>
</tr>

View File

@@ -10,15 +10,15 @@
<div class="widget_contents">
<table>
<tr>
<td class="label">Latitude</td>
<td class="label">$gettext["Latitude"]</td>
<td class="data">$station.latitude[0]&deg; $station.latitude[1]' $station.latitude[2]</td>
</tr>
<tr>
<td class="label">Longitude</td>
<td class="label">$gettext["Longitude"]</td>
<td class="data">$station.longitude[0]&deg; $station.longitude[1]' $station.longitude[2]</td>
</tr>
<tr>
<td class="label">Altitude</td>
<td class="label">$gettext["GeoAltitude"]</td>
<td class="data">$station.altitude</td>
</tr>
<tr>

View File

@@ -6,7 +6,7 @@
#encoding UTF-8
##
<!DOCTYPE html>
<html lang="en">
<html lang="$gettext.lang">
<head>
## This choice should match the #encoding directive above
<meta charset="UTF-8">
@@ -33,15 +33,15 @@
<div id="plot_group">
<div id="history_widget" class="widget">
<div id="plot_title" class="widget_title">History:&nbsp;&nbsp;
<div id="plot_title" class="widget_title">$gettext[$page]["Plots"]:&nbsp;&nbsp;
<a class="button_selected" id="button_history_day"
onclick="choose_history('day')">Day</a>
onclick="choose_history('day')">$gettext["Day"]</a>
<a class="button" id="button_history_week"
onclick="choose_history('week')">Week</a>
onclick="choose_history('week')">$gettext["Week"]</a>
<a class="button" id="button_history_month"
onclick="choose_history('month')">Month</a>
onclick="choose_history('month')">$gettext["Month"]</a>
<a class="button" id="button_history_year"
onclick="choose_history('year')">Year</a>
onclick="choose_history('year')">$gettext["Year"]</a>
</div>
<div id="history_day" class="plot_container">
<img src="daybarometer.png" alt="$obs.label.barometer"/>
@@ -160,8 +160,7 @@
</div>
<p class="footnote">
This station is controlled by <a href="http://weewx.com/">WeeWX</a>, an
experimental weather software system written in Python.
$gettext["footnote1"]<a href="http://weewx.com/">WeeWX</a>$gettext["footnote2"]
</p>
#include "analytics.inc"

178
skins/Seasons/lang/de.conf Normal file
View File

@@ -0,0 +1,178 @@
###############################################################################
# Localization File #
# German #
# Copyright (c) 2018-2021 Tom Keffer <tkeffer@gmail.com> and Matthew Wall #
# Copyright (c) 2021 Johanna Karen Roedenbeck #
# See the file LICENSE.txt for your rights. #
###############################################################################
[Units]
# The following section overrides the label used for each type of unit
[[Labels]]
meter = " m", " m"
day = " Tag", " Tage"
hour = " Stunde", " Stunden"
minute = " Minute", " Minuten"
second = " Sekunde", " Sekunden"
NONE = ""
[[Ordinates]]
# Ordinal directions. The last one is for no wind direction
directions = N, NNO, NO, ONO, O, OSO, SO, SSO, S, SSW, SW, WSW, W, WNW, NW, NNW, N/A
[Labels]
# Set to hemisphere abbreviations suitable for your location:
hemispheres = N, S, O, W
# Generic labels, keyed by an observation type.
[[Generic]]
dateTime = "Datum/Zeit"
interval = Intervall
altimeter = Luftdruck (QNH) # QNH
altimeterRate = Luftdruckänderung
barometer = Luftdruck # QFF
barometerRate = Luftdruckänderung
pressure = abs. Luftdruck # QFE
pressureRate = Luftdruckänderung
dewpoint = Taupunkt
ET = ET
heatindex = Hitzeindex
inHumidity = Raumluftfeuchte
inTemp = Raumtemperatur
inDewpoint = Raumtaupunkt
outHumidity = Luftfeuchte
outTemp = Außentemperatur
radiation = Sonnenstrahlung
rain = Regen
rainRate = Regen-Rate
UV = UV-Index
wind = Wind
windDir = Windrichtung
windGust = Böen Geschwindigkeit
windGustDir = Böen Richtung
windSpeed = Windgeschwindigkeit
windchill = Windchill
windgustvec = Böen-Vektor
windvec = Wind-Vektor
extraTemp1 = Temperatur1
extraTemp2 = Temperatur2
extraTemp3 = Temperatur3
appTemp = gefühlte Temperatur
appTemp1 = gefühlte Temperatur
THSW = THSW-Index
lightning_distance = Blitzentfernung
lightning_strike_count = Blitzanzahl
cloudbase = Wolkenuntergrenze
# used in Seasons skin but not defined
feel = gefühlte Temperatur
# Sensor status indicators
rxCheckPercent = Signalqualität
txBatteryStatus = Übertragerbatteriestatus
windBatteryStatus = Anemometerbatteriestatus
rainBatteryStatus = Regenmesserbatteriestatus
outTempBatteryStatus = Außentemperatursensorbatteriestatus
inTempBatteryStatus = Innentemperatursensorbatteriestatus
consBatteryVoltage = Konsolenbatteriestatus
heatingVoltage = Heizungsspannung
supplyVoltage = Versorgungsspannung
referenceVoltage = Referenzspannung
[Almanac]
# The labels to be used for the phases of the moon:
moon_phases = Neumond, zunehmend, Halbmond, zunehmend, Vollmond, abnehmend, Halbmond, abnehmend
[Texts]
# Section Titles
"Current Conditions" = Aktuelle Werte
"Celestial" = Sonne und Mond
"HiLo" = "Höchst- und Tiefstwerte"
"Sensor Status" = "Sensorenstatus"
"About" = "Stationsdaten"
"Statistics" = "Statistik"
# titlebar.inc
"Monthly Reports" = "Monatswerte"
"Yearly Reports" = "Jahreswerte"
"select month" = "Monat wählen"
"select year" = "Jahr wählen"
# identifier.inc
"Latitude" = "geogr. Breite"
"Longitude" = "geogr. Länge"
"GeoAltitude" = "Höhe ü. NN" # geographisch
# time spans
"Today" = Heute
"Day" = Tag
"Week" = Woche
"Month" = Monat
"Year" = Jahr
"Rainyear" = Regenjahr
"Rainyear1" = "Regen-"
"Rainyear2" = "jahr"
# footnote
"footnote1" = "Diese Station wird von "
"footnote2" = " gesteuert, einer experimentellen Wetter-Software, geschrieben in Python."
[[index]]
"Plots" = Diagramme
"Daylight" = "Tageslicht"
[[statistics]]
"Title" = "Statistik"
[[celestial]]
"Title" = "Sonne und Mond"
"Sun" = Sonne
"Moon" = Mond
"Rise" = Aufgang
"Transit" = Transit
"Set" = Untergang
"Start civil twilight" = Dämmerungsbeginn
"End civil twilight" = Dämmerungsende
"Daylight" = Tageslicht gesamt
"Azimuth" = Azimut
"AstroAltitude" = Höhe # astronomisch
"Right ascension" = Rektaszension
"Declination" = Deklination
"Solstice" = Sonnenwende # Solstitium
"Equinox" = Tagundnachtgleiche # Äquinoktium
"Full moon" = Vollmond
"New moon" = Neumond
"Phase" = Phase
[[RSS]]
"Weather Conditions" = Wetterbedingungen
"description" = "Aktuelle Werte und Tages-, Monats- und Jahreszusammenfassung"
"from" = aus
"Min outside temperature" = Außentemperatur Minimum
"Max outside temperature" = Außentemperatur Maximum
"Min inside temperature" = Innentemperatur Minimum
"Max inside temperature" = Innentemperatur Maximum
"Min barometer" = Luftdruck Minimum
"Max barometer" = Luftdruck Maximum
"Max wind" = Max Wind
"Rain today" = Regen heute
"Rain total for month" = Regen in diesem Monat
"Rain total for year" = Regen in diesem Jahr
"Weather Conditions at" = Wetter am
"Yearly Weather Summary as of" = Jahreszusammenfassung zum
"Monthly Weather Summary as of" = Monatszusammenfassung zum
"Daily Weather Summary as of" = Tageszusammenfassung für den

176
skins/Seasons/lang/en.conf Normal file
View File

@@ -0,0 +1,176 @@
###############################################################################
# Localization File #
# English #
# Copyright (c) 2018-2021 Tom Keffer <tkeffer@gmail.com> and Matthew Wall #
# Copyright (c) 2021 Johanna Karen Roedenbeck #
# See the file LICENSE.txt for your rights. #
###############################################################################
[Units]
[[Labels]]
day = " day", " days"
hour = " hour", " hours"
minute = " minute", " minutes"
second = " second", " seconds"
[[Ordinates]]
# Ordinal directions. The last one should be for no wind direction
directions = N, NNE, NE, ENE, E, ESE, SE, SSE, S, SSW, SW, WSW, W, WNW, NW, NNW, N/A
[Labels]
# Set to hemisphere abbreviations suitable for your location:
hemispheres = N, S, E, W
# Generic labels, keyed by an observation type.
[[Generic]]
dateTime = Time
interval = Interval
altimeter = Altimeter # QNH
altimeterRate = Altimeter Change Rate
barometer = Barometer # QFF
barometerRate = Barometer Change Rate
pressure = Pressure # QFE
pressureRate = Pressure Change Rate
dewpoint = Dew Point
ET = ET
heatindex = Heat Index
inHumidity = Inside Humidity
inTemp = Inside Temperature
inDewpoint = Inside Dew Point
outHumidity = Humidity
outTemp = Outside Temperature
radiation = Radiation
rain = Rain
rainRate = Rain Rate
UV = UV Index
wind = Wind
windDir = Wind Direction
windGust = Gust Speed
windGustDir = Gust Direction
windSpeed = Wind Speed
windchill = Wind Chill
windgustvec = Gust Vector
windvec = Wind Vector
windrun = Wind Run
extraTemp1 = Temperature1
extraTemp2 = Temperature2
extraTemp3 = Temperature3
appTemp = Apparent Temperature
appTemp1 = Apparent Temperature
THSW = THSW Index
lightning_distance = Lightning Distance
lightning_strike_count = Lightning Strikes
cloudbase = Cloud Base
# used in Seasons skin, but not defined
feel = apparent temperature
# Sensor status indicators
rxCheckPercent = Signal Quality
txBatteryStatus = Transmitter Battery
windBatteryStatus = Wind Battery
rainBatteryStatus = Rain Battery
outTempBatteryStatus = Outside Temperature Battery
inTempBatteryStatus = Inside Temperature Battery
consBatteryVoltage = Console Battery
heatingVoltage = Heating Battery
supplyVoltage = Supply Voltage
referenceVoltage = Reference Voltage
[Almanac]
# The labels to be used for the phases of the moon:
moon_phases = New, Waxing crescent, First quarter, Waxing gibbous, Full, Waning gibbous, Last quarter, Waning crescent
[Texts]
# Section Titles
"Current Conditions" = Current Conditions
"Celestial" = Celestial
"HiLo" = "High/Low"
"Sensor Status" = "Sensor Status"
"About" = "About this weather station"
"Statistics" = "Statistics"
# titlebar.inc
"Monthly Reports" = "Monthly Reports"
"Yearly Reports" = "Yearly Reports"
"select month" = "Select Month"
"select year" = "Select Year"
# identifier.inc
"Latitude" = "Latitude"
"Longitude" = "Longitude"
"GeoAltitude" = "Altitude" # geographic
# time spans
"Today" = Today
"Day" = Day
"Week" = Week
"Month" = Month
"Year" = Year
"Rainyear" = Rain Year
"Rainyear1" = "Rain"
"Rainyear2" = "Year"
# footnote
"footnote1" = "This station is controlled by "
"footnote2" = ", an experimental weather software system written in Python."
[[index]]
"Plots" = History
"Daylight" = Daylight
[[statistics]]
"Title" = "Statistics"
[[celestial]]
"Title" = "Celestial"
"Sun" = "Sun"
"Moon" = "Moon"
"Rise" = Rise
"Transit" = Transit
"Set" = Set
"Start civil twilight" = Start civil twilight
"End civil twilight" = End civil twilight
"Daylight" = Total daylight
"Azimuth" = Azimuth
"AstroAltitude" = Altitude # astronomical
"Right ascension" = Right ascension
"Declination" = Declination
"Solstice" = Solstice
"Equinox" = Equinox
"Full moon" = Full moon
"New moon" = New moon
"Phase" = Phase
[[RSS]]
"Weather Conditions" = Weather Conditions
"description" = "Current conditions, and daily, monthly, and yearly summaries"
"from" = from
"Min outside temperature" = Min outside temperature
"Max outside temperature" = Max outside temperature
"Min inside temperature" = Min inside temperature
"Max inside temperature" = Max inside temperature
"Min barometer" = Min barometer
"Max barometer" = Max barometer
"Max wind" = Max wind
"Rain today" = Rain today
"Rain total for month" = Rain total for month
"Rain total for year" = Rain total for year
"Weather Conditions at" = Weather Conditions at
"Yearly Weather Summary as of" = Yearly Weather Summary as of
"Monthly Weather Summary as of" = Monthly Weather Summary as of
"Daily Weather Summary as of" = Daily Weather Summary as of

View File

@@ -3,10 +3,10 @@
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" >
<channel>
<title>$station.location, Weather Conditions</title>
<title>$station.location, $gettext[$page]["Weather Conditions"]</title>
<link>$station.station_url</link>
<description>Current conditions, and daily, monthly, and yearly summaries</description>
<language>en-us</language>
<description>$gettext[$page]["description"]</description>
<language>$gettext.lang</language>
<pubDate>$current.dateTime.format("%a, %d %b %Y %H:%M:%S %Z")</pubDate>
<lastBuildDate>$current.dateTime.format("%a, %d %b %Y %H:%M:%S %Z")</lastBuildDate>
@@ -18,116 +18,116 @@
<title>Weather Conditions at $current.dateTime</title>
<link>$station.station_url</link>
<description>
Outside temperature: $current.outTemp;
Barometer: $current.barometer;
Wind: $current.windSpeed from $current.windDir;
Rain rate: $current.rainRate;
Inside temperature: $current.inTemp
$obs.label.outTemp: $current.outTemp;
$obs.label.barometer: $current.barometer;
$obs.label.wind: $current.windSpeed $gettext[$page]["from"] $current.windDir;
$obs.label.rainRate: $current.rainRate;
$obs.label.inTemp: $current.inTemp
</description>
<pubDate>$current.dateTime.format("%a, %d %b %Y %H:%M:%S %Z")</pubDate>
<geo:lat>$station.latitude_f</geo:lat>
<geo:long>$station.longitude_f</geo:long>
<content:encoded><![CDATA[
<p>
Time: $current.dateTime<br/>
Outside Temperature: $current.outTemp<br/>
Inside Temperature: $current.inTemp<br/>
Wind Chill: $current.windchill<br/>
Heat Index: $current.heatindex<br/>
Dewpoint: $current.dewpoint<br/>
Humidity: $current.outHumidity<br/>
Barometer: $current.barometer<br/>
Wind: $current.windSpeed from $current.windDir<br/>
Rain Rate: $current.rainRate<br/>
$obs.label.dateTime: $current.dateTime<br/>
$obs.label.outTemp: $current.outTemp<br/>
$obs.label.inTemp: $current.inTemp<br/>
$obs.label.windchill: $current.windchill<br/>
$obs.label.heatindex: $current.heatindex<br/>
$obs.label.dewpoint: $current.dewpoint<br/>
$obs.label.outHumidity: $current.outHumidity<br/>
$obs.label.barometer: $current.barometer<br/>
$obs.label.wind: $current.windSpeed $gettext[$page]["from"] $current.windDir<br/>
$obs.label.rainRate: $current.rainRate<br/>
</p>
]]></content:encoded>
</item>
<item>
<title>Daily Weather Summary as of $current.dateTime</title>
<title>$gettext[$page]["Daily Weather Summary as of"] $current.dateTime</title>
<link>$station.station_url</link>
<description>
Min outside temperature: $day.outTemp.min at $day.outTemp.mintime;
Max outside temperature: $day.outTemp.max at $day.outTemp.maxtime;
Min inside temperature: $day.inTemp.min at $day.inTemp.mintime;
Max inside temperature: $day.inTemp.max at $day.inTemp.maxtime;
Min barometer: $day.barometer.min at $day.barometer.mintime;
Max barometer: $day.barometer.max at $day.barometer.maxtime;
Max wind : $day.wind.max from $day.wind.gustdir at $day.wind.maxtime;
Rain today: $day.rain.sum
$gettext[$page]["Min outside temperature"]: $day.outTemp.min at $day.outTemp.mintime;
$gettext[$page]["Max outside temperature"]: $day.outTemp.max at $day.outTemp.maxtime;
$gettext[$page]["Min inside temperature"]: $day.inTemp.min at $day.inTemp.mintime;
$gettext[$page]["Max inside temperature"]: $day.inTemp.max at $day.inTemp.maxtime;
$gettext[$page]["Min barometer"]: $day.barometer.min at $day.barometer.mintime;
$gettext[$page]["Max barometer"]: $day.barometer.max at $day.barometer.maxtime;
$gettext[$page]["Max wind"] : $day.wind.max $gettext[$page]["from"] $day.wind.gustdir at $day.wind.maxtime;
$gettext[$page]["Rain today"]: $day.rain.sum
</description>
<pubDate>$current.dateTime.format("%a, %d %b %Y %H:%M:%S %Z")</pubDate>
<geo:lat>$station.latitude_f</geo:lat>
<geo:long>$station.longitude_f</geo:long>
<content:encoded><![CDATA[
<p>
Day: $day.dateTime.format("%d %b %Y")<br/>
Min Outside Temperature: $day.outTemp.min at $day.outTemp.mintime<br/>
Max Outside Temperature: $day.outTemp.max at $day.outTemp.maxtime<br/>
Min Inside Temperature: $day.inTemp.min at $day.inTemp.mintime<br/>
Max Inside Temperature: $day.inTemp.max at $day.inTemp.maxtime<br/>
Min Barometer: $day.barometer.min at $day.barometer.mintime<br/>
Max Barometer: $day.barometer.max at $day.barometer.maxtime<br/>
Max Wind : $day.wind.max from $day.wind.gustdir at $day.wind.maxtime<br/>
Rain today: $day.rain.sum<br/>
$gettext["Day"]: $day.dateTime.format("%d %b %Y")<br/>
$gettext[$page]["Min outside temperature"]: $day.outTemp.min at $day.outTemp.mintime<br/>
$gettext[$page]["Max outside temperature"]: $day.outTemp.max at $day.outTemp.maxtime<br/>
$gettext[$page]["Min inside temperature"]: $day.inTemp.min at $day.inTemp.mintime<br/>
$gettext[$page]["Max inside temperature"]: $day.inTemp.max at $day.inTemp.maxtime<br/>
$gettext[$page]["Min barometer"]: $day.barometer.min at $day.barometer.mintime<br/>
$gettext[$page]["Max barometer"]: $day.barometer.max at $day.barometer.maxtime<br/>
$gettext[$page]["Max wind"] : $day.wind.max $gettext[$page]["from"] $day.wind.gustdir at $day.wind.maxtime<br/>
$gettext[$page]["Rain today"]: $day.rain.sum<br/>
</p>
]]></content:encoded>
</item>
<item>
<title>Monthly Weather Summary as of $current.dateTime</title>
<title>$gettext[$page]["Monthly Weather Summary as of"]) $current.dateTime</title>
<link>$station.station_url</link>
<description>
Min outside temperature: $month.outTemp.min at $month.outTemp.mintime;
Max outside temperature: $month.outTemp.max at $month.outTemp.maxtime;
Min inside temperature: $month.inTemp.min at $month.inTemp.mintime;
Max inside temperature: $month.inTemp.max at $month.inTemp.maxtime;
Min barometer: $month.barometer.min at $month.barometer.mintime;
Max barometer: $month.barometer.max at $month.barometer.maxtime;
Max wind : $month.wind.max from $month.wind.gustdir at $month.wind.maxtime;
Rain total for month: $month.rain.sum
$gettext[$page]["Min outside temperature"]: $month.outTemp.min at $month.outTemp.mintime;
$gettext[$page]["Max outside temperature"]: $month.outTemp.max at $month.outTemp.maxtime;
$gettext[$page]["Min inside temperature"]: $month.inTemp.min at $month.inTemp.mintime;
$gettext[$page]["Max inside temperature"]: $month.inTemp.max at $month.inTemp.maxtime;
$gettext[$page]["Min barometer"]: $month.barometer.min at $month.barometer.mintime;
$gettext[$page]["Max barometer"]: $month.barometer.max at $month.barometer.maxtime;
$gettext[$page]["Max wind"] : $month.wind.max $gettext[$page]["from"] $month.wind.gustdir at $month.wind.maxtime;
$gettext[$page]["Rain total for month"]: $month.rain.sum
</description>
<pubDate>$current.dateTime.format("%a, %d %b %Y %H:%M:%S %Z")</pubDate>
<content:encoded><![CDATA[
<p>
Month: $month.dateTime.format("%B %Y")<br/>
Max Outside Temperature: $month.outTemp.max at $month.outTemp.maxtime<br/>
Min Outside Temperature: $month.outTemp.min at $month.outTemp.mintime<br/>
Max Inside Temperature: $month.inTemp.max at $month.inTemp.maxtime<br/>
Min Inside Temperature: $month.inTemp.min at $month.inTemp.mintime<br/>
Min Barometer: $month.barometer.min at $month.barometer.mintime<br/>
Max Barometer: $month.barometer.max at $month.barometer.maxtime<br/>
Max Wind : $month.wind.max from $month.wind.gustdir at $month.wind.maxtime<br/>
Rain total for month: $month.rain.sum<br/>
$gettext["Month"]: $month.dateTime.format("%B %Y")<br/>
$gettext[$page]["Max outside temperature"]: $month.outTemp.max at $month.outTemp.maxtime<br/>
$gettext[$page]["Min outside temperature"]: $month.outTemp.min at $month.outTemp.mintime<br/>
$gettext[$page]["Max inside temperature"]: $month.inTemp.max at $month.inTemp.maxtime<br/>
$gettext[$page]["Min inside temperature"]: $month.inTemp.min at $month.inTemp.mintime<br/>
$gettext[$page]["Min barometer"]: $month.barometer.min at $month.barometer.mintime<br/>
$gettext[$page]["Max barometer"]: $month.barometer.max at $month.barometer.maxtime<br/>
$gettext[$page]["Max wind"] : $month.wind.max $gettext[$page]["from"] $month.wind.gustdir at $month.wind.maxtime<br/>
$gettext[$page]["Rain total for month"]: $month.rain.sum<br/>
</p>
]]></content:encoded>
</item>
<item>
<title>Yearly Weather Summary as of $current.dateTime</title>
<title>$gettext[$page]["Yearly Weather Summary as of"] $current.dateTime</title>
<link>$station.station_url</link>
<description>
Min outside temperature: $year.outTemp.min at $year.outTemp.mintime;
Max outside temperature: $year.outTemp.max at $year.outTemp.maxtime;
Min inside temperature: $year.inTemp.min at $year.inTemp.mintime;
Max inside temperature: $year.inTemp.max at $year.inTemp.maxtime;
Min barometer: $year.barometer.min at $year.barometer.mintime;
Max barometer: $year.barometer.max at $year.barometer.maxtime;
Max wind : $year.wind.max from $year.wind.gustdir at $year.wind.maxtime;
Rain total for year: $year.rain.sum
$gettext[$page]["Min outside temperature"]: $year.outTemp.min at $year.outTemp.mintime;
$gettext[$page]["Max outside temperature"]: $year.outTemp.max at $year.outTemp.maxtime;
$gettext[$page]["Min inside temperature"]: $year.inTemp.min at $year.inTemp.mintime;
$gettext[$page]["Max inside temperature"]: $year.inTemp.max at $year.inTemp.maxtime;
$gettext[$page]["Min barometer"]: $year.barometer.min at $year.barometer.mintime;
$gettext[$page]["Max barometer"]: $year.barometer.max at $year.barometer.maxtime;
$gettext[$page]["Max wind"] : $year.wind.max $gettext[$page]["from"] $year.wind.gustdir at $year.wind.maxtime;
$gettext[$page]["Rain total for year"]: $year.rain.sum
</description>
<pubDate>$current.dateTime.format("%a, %d %b %Y %H:%M:%S %Z")</pubDate>
<content:encoded><![CDATA[
<p>
Year: $year.dateTime.format("%Y")<br/>
Max Outside Temperature: $year.outTemp.max at $year.outTemp.maxtime<br/>
Min Outside Temperature: $year.outTemp.min at $year.outTemp.mintime<br/>
Max Inside Temperature: $year.inTemp.max at $year.inTemp.maxtime<br/>
Min Inside Temperature: $year.inTemp.min at $year.inTemp.mintime<br/>
Min Barometer: $year.barometer.min at $year.barometer.mintime<br/>
Max Barometer: $year.barometer.max at $year.barometer.maxtime<br/>
Max Wind : $year.wind.max from $year.wind.gustdir at $year.wind.maxtime<br/>
Rain total for year: $year.rain.sum<br/>
$gettext["Year"]: $year.dateTime.format("%Y")<br/>
$gettext[$page]["Max outside temperature"]: $year.outTemp.max at $year.outTemp.maxtime<br/>
$gettext[$page]["Min outside temperature"]: $year.outTemp.min at $year.outTemp.mintime<br/>
$gettext[$page]["Max inside temperature"]: $year.inTemp.max at $year.inTemp.maxtime<br/>
$gettext[$page]["Min inside temperature"]: $year.inTemp.min at $year.inTemp.mintime<br/>
$gettext[$page]["Min barometer"]: $year.barometer.min at $year.barometer.mintime<br/>
$gettext[$page]["Max barometer"]: $year.barometer.max at $year.barometer.maxtime<br/>
$gettext[$page]["Max wind"] : $year.wind.max $gettext[$page]["from"] $year.wind.gustdir at $year.wind.maxtime<br/>
$gettext[$page]["Rain total for year"]: $year.rain.sum<br/>
</p>
]]></content:encoded>
</item>

View File

@@ -45,7 +45,7 @@
#if $have_conn or $have_battery_status or $have_voltage
<div id='sensors_widget' class="widget">
<div class="widget_title">
<a href="telemetry.html">Sensor Status</a>
<a href="telemetry.html">$gettext["Sensor Status"]</a>
<a class="widget_control"
onclick="toggle_widget('sensors')">&diams;</a>
</div>

View File

@@ -3,7 +3,7 @@
#errorCatcher Echo
#encoding UTF-8
<!DOCTYPE html>
<html lang="en">
<html lang="$gettext.lang">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>$station.location Statistics</title>
@@ -39,7 +39,7 @@
#include "titlebar.inc"
<div id="contents">
<p><a href="index.html">&#10096; Current Conditions</a></p>
<p><a href="index.html">&#10096; $gettext["Current Conditions"]</a></p>
<div id="widget_group">
#include "statistics.inc"

View File

@@ -8,7 +8,7 @@
<div id="statistics_widget" class="widget">
<div class="widget_title">
Statistics
$gettext[$page].Title
</div>
<div class="widget_contents">
@@ -17,11 +17,11 @@
<tr>
<td></td>
<td></td>
<th>Today</th>
<th class="hilo_week">Week</th>
<th class="hilo_month">Month</th>
<th class="hilo_year">Year</th>
<th class="hilo_rainyear">Rain year</th>
<th>$gettext["Today"]</th>
<th class="hilo_week">$gettext["Week"]</th>
<th class="hilo_month">$gettext["Month"]</th>
<th class="hilo_year">$gettext["Year"]</th>
<th class="hilo_rainyear">$gettext["Rainyear"]</th>
</tr>
<tr>
<td class="label">$obs.label.outTemp</td>

View File

@@ -27,7 +27,7 @@
<div id="sunmoon_widget" class="widget">
<div class="widget_title">
<a href="celestial.html">Celestial</a>
<a href="celestial.html">$gettext["Celestial"]</a>
<a class="widget_control"
onclick="toggle_widget('sunmoon')">&diams;</a>
</div>
@@ -37,21 +37,21 @@
<table class="celestial">
<tr><th>&#9728;</th><td></td><td></td><th>&#9789;</th><td></td></tr>
<tr>
<td class="label">Rise</td>
<td class="label">$gettext["celestial"]["Rise"]</td>
<td class="data">$almanac.sun.rise.format(None_string=$sun_None)</td>
<td>&nbsp;</td>
<td class="label">Rise</td>
<td class="label">$gettext["celestial"]["Rise"]</td>
<td class="data">$almanac.moon.rise</td>
</tr>
<tr>
<td class="label">Set</td>
<td class="label">$gettext["celestial"]["Set"]</td>
<td class="data">$almanac.sun.set.format(None_string=$sun_None)</td>
<td>&nbsp;</td>
<td class="label">Set</td>
<td class="label">$gettext["celestial"]["Set"]</td>
<td class="data">$almanac.moon.set</td>
</tr>
<tr>
<td class="label">Daylight</td>
<td class="label">$gettext[$page]["Daylight"]</td>
<td class="data">$daylight_str</td>
<td>&nbsp;</td>
<td class="label"></td>

View File

@@ -4,7 +4,7 @@
#encoding UTF-8
<!DOCTYPE html>
<html lang="en">
<html lang="$gettext.lang">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>$station.location</title>
@@ -23,7 +23,7 @@
#include "titlebar.inc"
<div id="contents">
<p><a href="index.html">&#10096; Current Conditions</a></p>
<p><a href="index.html">&#10096; $gettext["Current Conditions"]</a></p>
<div id="report" class="tabular"></div>
</div>

View File

@@ -18,7 +18,7 @@
#end def
<!DOCTYPE html>
<html lang="en">
<html lang="$gettext.lang">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>$station.location Telemetry</title>
@@ -31,7 +31,7 @@
#include "titlebar.inc"
<div id="contents">
<p><a href="index.html">&#10096; Current Conditions</a></p>
<p><a href="index.html">&#10096; $gettext["Current Conditions"]</a></p>
<div id="widget_group">
#include "sensors.inc"
@@ -41,13 +41,13 @@
<div id="history_widget" class="widget">
<div id="plot_title" class="widget_title">Telemetry:&nbsp;&nbsp;
<a class="button_selected" id="button_history_day"
onclick="choose_history('day')">Day</a>
onclick="choose_history('day')">$gettext["Day"]</a>
<a class="button" id="button_history_week"
onclick="choose_history('week')">Week</a>
onclick="choose_history('week')">$gettext["Week"]</a>
<a class="button" id="button_history_month"
onclick="choose_history('month')">Month</a>
onclick="choose_history('month')">$gettext["Month"]</a>
<a class="button" id="button_history_year"
onclick="choose_history('year')">Year</a>
onclick="choose_history('year')">$gettext["Year"]</a>
</div>
$period_plots($day, 'day')

View File

@@ -11,20 +11,20 @@
</div>
<div id="rss_link"><a href="rss.xml">RSS</a></div>
<div id="reports">
Monthly Reports:
$gettext["Monthly Reports"]:
<select name="reports" onchange="openTabularFile(value)">
#for $monthYear in $SummaryByMonth
<option value="$monthYear">$monthYear</option>
#end for
<option selected>- Select Month -</option>
<option selected>- $gettext["select month"] -</option>
</select>
<br/>
Yearly Reports:
$gettext["Yearly Reports"]:
<select name="reports" onchange="openTabularFile(value)">
#for $yr in $SummaryByYear
<option value="$yr">$yr</option>
#end for
<option selected>- Select Year -</option>
<option selected>- $gettext["select year"] -</option>
</select>
<br/>
</div>

View File

@@ -158,6 +158,8 @@ version = 4.6.0a1
# The SeasonsReport uses the 'Seasons' skin, which contains the
# images, templates and plots for the report.
skin = Seasons
lang = en
units_base = US
enable = true
[[SmartphoneReport]]