1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
-*- mode: org -*-
#+TITLE: sisudoc spine (doc_reform) object-centric document abstraction
#+DESCRIPTION: documents - structuring, publishing in multiple formats & search
#+SUMMARY: process markup document, create document abstraction
#+FILETAGS: :spine:abstraction:
#+AUTHOR: Ralph Amissah
#+EMAIL: [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]]
#+COPYRIGHT: Copyright (C) 2015 (continuously updated, current 2026) Ralph Amissah
#+LANGUAGE: en
#+STARTUP: content hideblocks hidestars noindent entitiespretty
#+PROPERTY: header-args+ :eval never-export :exports code
#+PROPERTY: header-args+ :noweb yes :padline no
#+PROPERTY: header-args+ :results silent :cache no
#+PROPERTY: header-args+ :mkdirp yes
#+OPTIONS: H:3 num:nil toc:t \n:t ::t |:t ^:nil -:t f:t *:t
- magic single double-quote → " ← FIX changes hilighting behavior (occuring
after it) in org document. INVESTIGATE (org-mode CONFIG?) FIND & FIX
- [[./doc-reform.org][doc-reform.org]] [[./][org/]]
* (translation) po4a setup
#+HEADER: :tangle "../src/sisudoc/outputs/io_out/po4a_cfg.d"
#+HEADER: :noweb yes
#+BEGIN_SRC d
<<doc_header_including_copyright_and_license>>
/++
module po4a_cfg;<BR>
- the po4a configuration for a document, generated from its manifest and
the files its markup names<BR>
- written for tools/po4a/po4a.cfg, so its paths are relative to there
+/
module sisudoc.outputs.io_out.po4a_cfg;
@system:
/+ ↓ po4a's configuration, derived rather than kept
The sample this replaces kept a Makefile that built po4a.cfg by globbing
a language directory and listing what it found. Spine already knows both
halves without looking: the manifest says which languages a document
has, and the markup says which files it is made of, through the << lines
the parser follows. Deriving the configuration from those two means it
cannot disagree with the document, which a hand-kept file eventually
does: a language added to the manifest and forgotten in the Makefile
produces a translation nobody updates.
.
It is derived, so it is not kept in git. The sample repository's
whitelist admits pot/ and po/ and not this.
.
neverwrap is deliberately NOT set, and the reason is worth keeping.
.
Without it po4a rewraps its output at about 75 columns, so a document
whose markup keeps one paragraph on one long line comes back reflowed.
That is untidy: it changes no object, since sisu delimits on blank
lines, but it churns every translated file in a diff and leaves the
source language and its translations formatted unlike each other. The
obvious thing is to turn wrapping off.
.
Measured on live-manual, same catalogues and same English, the option
the only difference:
.
fuzzy before with neverwrap without
ca 1 889 5
de 8 103 10
it 149 804 152
.
of 1126 strings. po4a will not use a fuzzy translation, so each one
renders as the source language: Catalan's coverage would fall from about
46% to about 12%, and Spanish, French and Japanese with it. Setting the
option re-extracts the strings in a form the existing catalogues do not
match, and four fifths of nine languages' work stops being used.
.
Tidy formatting is not worth that. The wrapping stays.
+/
template spinePo4aConfig() {
string po4aConfig(M)(M doc_matters) {
import std.algorithm : sort;
import std.array : array, join;
import std.conv : to;
import std.file : exists;
import std.path : baseName;
string _src_lang = doc_matters.src.language;
/+ ↓ the languages po4a is to produce, which is every language the
manifest lists except the one being translated from
+/
string[] _targets;
foreach (_lang; doc_matters.pod.manifest_list_of_languages) {
if (_lang != _src_lang) {
_targets ~= _lang;
}
}
/+ ↓ the files the document is made of: its master, and every insert the
markup names. In manifest order rather than directory order, so the
configuration is the same however a filesystem chooses to list a
directory.
+/
string[] _files;
_files ~= doc_matters.src.filename;
string[] _inserts;
foreach (_insert; doc_matters.srcs.file_insert_list) {
_inserts ~= _insert.baseName;
}
_inserts = _inserts.sort.array;
_files ~= _inserts;
/+ ↓ paths are relative to tools/po4a/, where this file belongs +/
enum string _to_text = "../../media/text";
string _o;
_o ~= "# po4a configuration for " ~ doc_matters.src.filename_base ~ "\n";
_o ~= "# generated by spine from pod.manifest and the markup; not kept in git\n";
_o ~= "# run from the directory this file is in\n";
_o ~= "\n";
/+ ↓ --keep 0 is not optional here, it is the difference between
regenerating a document and destroying it.
.
po4a will not write a translated file that falls below a
completeness threshold, and that threshold defaults to 80%. A
partially translated document is the normal state of one being
worked on, and sisu's own behaviour covers it: an untranslated
string falls back to the source text, so a file at 3% is mostly the
source language and entirely readable. (Measured on live-manual at
the default: 181 of its 189 translated files would be discarded, and
nine languages would collapse to eight surviving files. It would not
look like a failure either, because what remains reads as the
document reverting to its source language.)
.
The Makefile this replaces passed --keep 0 for exactly this reason.
+/
_o ~= "[options] --keep 0 --package-name " ~ doc_matters.src.filename_base ~ "\n";
_o ~= "\n";
_o ~= "[po4a_langs] " ~ _targets.join(" ") ~ "\n";
_o ~= "[po4a_paths] pot/$master.pot $lang:po/$lang/$master.po\n";
_o ~= "\n";
foreach (_f; _files) {
_o ~= "[type: text] " ~ _to_text ~ "/" ~ _src_lang ~ "/" ~ _f
~ " $lang:" ~ _to_text ~ "/$lang/" ~ _f ~ "\n";
}
/+ ↓ index.html.in is not markup and no << line names it, so it is found
by asking whether the source language has one. live-manual does, the
Makefile it replaces carried it as xhtml, and the sample
repository's whitelist admits index.html.in.pot and .po by name.
Left out, regenerating would quietly drop those catalogue entries.
+/
string _index_in = doc_matters.pod.manifest_path
~ "/media/text/" ~ _src_lang ~ "/index.html.in";
if (_index_in.exists) {
_o ~= "[type: xhtml] " ~ _to_text ~ "/" ~ _src_lang ~ "/index.html.in"
~ " $lang:" ~ _to_text ~ "/$lang/index.html.in\n";
}
return _o;
}
}
#+END_SRC
* org includes
** project version
#+NAME: spine_version
#+HEADER: :noweb yes
#+BEGIN_SRC emacs-lisp
<<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:spine_project_version()>>
#+END_SRC
** year
#+NAME: year
#+HEADER: :noweb yes
#+BEGIN_SRC emacs-lisp
<<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:year()>>
#+END_SRC
** document header including copyright & license
#+NAME: doc_header_including_copyright_and_license
#+HEADER: :noweb yes
#+BEGIN_SRC emacs-lisp
<<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:spine_doc_header_including_copyright_and_license()>>
#+END_SRC
* __END__
|