Thank you for your interest in helping us localize HTML Tidy and LibTidy. Users throughout the world will thank you.
The document describes Tidy's localization philosophy and instructs you on how
you can use standard gettext
tools to generate language and region
localizations that will work with Tidy. Optionally instructions are included in
the event that you want to build Tidy with your new language.
- Introduction
- How to Contribute
- Adding Languages to Tidy
- Best Practices
- Testing
- gettext
- poconvert.rb
- Create a new POT file
- Create a new POT file with non-English
msgid
strings - Convert an existing H to PO
- Convert an existing H to PO using a different
msgid
language - Create a blank PO file for a particular region
- Create a Tidy Language Header H file
- Prepare your non-English PO for a PR
- Update your PO to match the new POT
- Help Tidy Get Better
HTML Tidy is built around the localization file language_en.h
; without this
file HTML Tidy will not work. As such all language localization work
originates from this single file.
Language localizations use header files that are identical to language_en.h
,
except that they have different strings. For the convenience of language
translators, though, Tidy source code includes a Ruby poconvert.rb
script
that enables optional gettext PO/POT work streams that may be more comfortable
to them.
HTML Tidy provides PO and POT files for language translations. The file
tidy.pot
is the correct template to use as a basis for new translations. In a
typical gettext
workflow a translator will use the tidy.pot
file to create a
language translation PO file that contains original English strings and the
translated strings.
If a language has already been translated (or if the translation has begun) then
PO files may already exist. These files are named language_ll.po
or
langage_ll_CC.po
, where ll
represents the language code, and optionally,
CC
represents the region code of the translation.
Tidy does not use MO files that gettext
tools generate from PO files.
Please note that these PO and POT files are provided for translator convenience only. Tidy's header files constitute the true, controlled source code for Tidy.
Tidy does not use gettext
to display strings and so gettext
-generated MO
files are not necessary. Instead translated PO files must be converted to Tidy's
language header H file format. Translators are not required to perform this
step, but we provide a tool to perform this function if desired.
Experienced users and translators of PO files may note that we use the PO file's
msgctxt
field a bit uniquely. Rather than point to a line in the source code,
it contains a reference to the string's identifier. Because the PO format does
not allow for arbitrary metadata this is a requirement for generating our
header files.
If you're the type of translator the does dig into the source code, then this
msgtext
symbol is still useful to you and adds a single extra step to finding
where a string is in context: a symbol or string search using the msgctxt
value will reveal the context in source code.
Finally the msgid
field is a throwaway; Tidy's language tools do not use this
value and so it's only for the translator's convenience. This fact makes it
convenient for translators to translate from languages other than English,
which is fully supported by our tools.
Please don't use gettext
' tools with our PO and POT files (unless you are
using our strings for a different project). Instead all workflows can be
accomplished with our poconvert.rb
tool.
More information about this tool can be found below.
If you've not already cloned the HTML Tidy source code repository that will be your first step.
In the localize/translations/
directory you can find existing languages, e.g.,
tidy.pot
(Tidy's POT template for translations).language_en_gb.po
(British English variants for the built in language)- …and perhaps more.
In the src/
directory you can find the master files for existing languages,
e.g.,
language_en.h
(Tidy's native, built-in language, mostly U.S. English)language_en_gb.po
(British English variants for the built in language)- …and perhaps more.
Although the header files are the master files for HTML Tidy, we understand that not all potential translators want to edit C files directly. Therefore as an option, the following workflow to use POT and PO files is offered.
If the language that you want to work on is already present:
- Simply open the file in your favorite PO editor and then get to work.
- Note that although you can use a text editor, we recommend that you use a dedicated PO editor so that you don't accidentally make the file illegible to our conversion utility.
If the language that you want to work on is not already present:
- You can open
tidy.pot
in your favorite PO editor and use its functions to begin a new translation into your desired language. - Note that although you can use a text editor, we recommend that you use a dedicated PO editor so that you don't accidentally make the file illegible to our conversion utility.
- To perform the work manually:
- Copy
tidy.pot
tolanguage_ll.po
(for a non-regional variant, or base language), or tolanguage_ll_cc.po
(for a region-specific variant), wherell
indicates the two letter language code andcc
indicates the two letter region or country code. - Change the pertinent PO header section accordingly.
- Copy
- Use
poconvert.rb
to generate a PO:poconvert.rb msginit --locale ll
, wherell
indicates the language code for the language you want to translate to. The tool recognizes the same languages asgettext
'msginit
. If your chosen language is not supported, then please see the manual method, above.- See also
poconvert.rb help
for more options.
- See GNU's The Format of PO Files for more specific instructions and important information.
Once your translation is complete commit your entire HTML Tidy repository to
GitHub and issue a pull request (PR) against the master
branch. If accepted a
friendly developer will convert your PO into a format useful to Tidy if your
PR is a PO, or will simply merge your changed header file if you changed it
directly.
You are also welcome to perform any conversions yourself, add new languages to Tidy, and issue a PR for the whole change.
- Fork the repository to your GitHub account.
- Optionally create a topical branch - a branch whose name is succinct but explains what you're doing, such as "localize Portuguese".
- Make your changes, committing at logical breaks.
- Push your work to your personal account.
- Create a pull request.
- Watch for comments or acceptance.
If you are working with PO files then please only commit PO files with
English msgid
fields. The gettext
convention specifies only English
msgid
, and other translators may not understand the original strings.
Our poconvert.rb
script can generate PO files using another language as
msgid
. This can be very useful if it's easier for you to translate from
another language instead of English. It can also be useful for translating from
a base language to a regional variant, such as from Spanish to Mexican Spanish.
If you choose to work locally with a non-English PO, you can easily convert
your PO to a Tidy header file and back to an English-based PO using our
poconvert.rb
script. See its documentation (poconvert.rb help
) for
instructions.
Although we don't require you to follow these steps to contribute a language to Tidy, you may want to add the language to Tidy yourself to test the translation, or to save one of the developer team a few extra steps.
- Generate the header files if necessary:
- Convert your PO file to a Tidy header file by executing
poconvert.rb msgfmt <path_to_your_file.po>
. Note that on Windows you will likely have to preface this line withruby
. - The tool should generate a file named
language_ll_cc.h
in the working directory, wherell_cc
will be replaced with the language/region of your translation. - Copy this
.h
file intosrc/
.
- Convert your PO file to a Tidy header file by executing
- Modify Tidy's source:
- Edit the file
src/language.c
to ensure that the new.h
file you added is in the#include
section. - Look for the
static tidyLanguagesType tidyLanguages
structure starting near line 40, and look for the commentThese languages are installed.
. You can add your new language to the list along with the other languages present, following the same format.
- Edit the file
- Build Tidy:
- Build Tidy per the usual instructions, and try it out using the
-lang
option.
- Build Tidy per the usual instructions, and try it out using the
HTML Tidy will fallback from the specified language to the base language and
then finally to the default English as required. This means, for example, a
programmer might set libtidy
to use “es_mx”, and if it doesn’t exist Tidy
will automatically use “es”. If that doesn’t exist libtidy
will continue to
use whatever language it is currently using.
HTML Tidy will also fallback for individual strings. For example if libtidy
is set to use “es_mx” and a particular string is requested and not found, the
library will look for the string in “es”. If the string is not found there then
the “en” string will be given.
Because of this inheritance we hope to localize base languages first, as the
only strings then required for regional variants are the strings that differ.
This will help us keep HTML Tidy and libtidy
small.
If you are working on a regional variation (such as “us_CA”) please only localize strings that are actually different from the base language!
Please note that HTML Tidy does not currently support positional parameters. Due to the nature of most of Tidy's output, it's not expected that they will be required. In any case, please translate strings so that substitution values are in the same order as the original string.
We hope to develop a comprehensive test suite in the future, but in the meantime you can test localized output like this.
Use the -lang
/-language
option and specify a POSIX or Windows language name.
This option should be first option used because the console application parses
and acts on options first-in, first-out.
On Unix/Mac and Linux operating systems you can change your shell’s locale temporarily with:
export LANG=en_GB
export LC_ALL=en_GB
…substituting, of course the language of your choice.
East Asian languages are completely supported and have been tested on Linux, Mac OS X, and Windows, although Windows requires you to set your operating system (not the console locale!) to an East Asian locale to enable this in Windows Console and PowerShell. Note that PowerShell ISE always supports East Asian languages without requiring you to change your operating system locale.
Although HTML Tidy uses gettext
-compatible tools and PO files for language
localization, Tidy itself does not use gettext
. Tidy's build philosophy is
build it anywhere and build it with anything. As gettext
is not universally
available on every platform under the sun, Tidy cannot count on gettext
.
Instead Tidy builds all translations into its library (and command line executable if built monolithically), and can run on virtually any general purpose computer with any operating system.
While this does not pose a significant problem for storage or execution space
on modern PC's, we understand that certain applications may still be space
critical. As such it's trivial to build Tidy without this extra language
support using the -DSUPPORT_LOCALIZATIONS=NO
switch.
Tidy's source code includes a Ruby batch file called poconvert.rb
which can be
used to generate POT, PO, and H files, and convert them back and forth. It has
been designed to work in a similar fashion as gettext
's tools, and includes
conveniences that let translators work in different source languages. Please
use poconvert.rb help
for complete information (ruby poconvert.rb help
on
Windows).
Note that you must install Ruby on your system, as well as install the required
dependencies. These can be manually installed with [sudo] gem install xxx
,
where xxx
represents the packages listed in Gemfile
. For convenience, if you
have the Bundler gem installed, you can bundle install
for automated
dependency installation.
Also take note of these two important characteristics:
poconvert.rb
is currently dependent on its current path. You can move it from its current location, but you will have to change the values of the@@default_en
and@@header_template
variables within the script.- All files will be output in the current working directory. This will prevent accidental overwrites of important files while we all get used to the workflows.
Below are some sample workflows.
Although we provide tidy.pot
in the source, you can generate your own.
./poconvert.rb xgettext
This will put a fresh, new copy of tidy.pot
in the working directory.
Although gettext
officially recognizes English as the one, true source
language for PO and POT files, if you're more comfortable translating from a
non-English language, we can support you.
./poconvert.rb xgettext <language_cc_ll.h>
Where <language_cc_ll.h>
is the path to an existing Tidy language header file.
This will produce a tidy.pot
using the translated strings as msgid
, using
English as a backup when translated strings are not present.
This can be valuable in producing regional variant translations, e.g., when
translating from es
to es_mx
.
In many cases you may want to have a fresh PO generated from a Tidy H file. This can be accomplished with:
./poconvert.rb msgunfmt <language_cc_ll.h>
If you want to generate a fresh PO file from a Tidy H file, but also want to have untranslated strings from a language other than English, try:
./poconvert.rb msgunfmt <language_cc_ll.h> --baselang=<other-language_cc_ll.h>
./poconvert.rb msginit
or
./poconvert.rb msginit --locale=LOCALE
The first example will try to guess your current region, and the second will use a region specified.
Tidy only knows about the same regions that gettext
knows; if our msginit
does not recognize the region you specify, you will have to create a new PO
and modify the region settings yourself.
To create the blank PO using msgid
strings from a different Tidy language,
you can use:
./poconvert.rb msginit <language_cc_ll.h> [--locale=LOCALE]
When you're ready to include the language in Tidy, you can generate its header file with:
./poconvert.rb msgfmt <language_cc_ll.po>
In the event you are creating a regional variant of a language, it's an
excellent idea to have Tidy exclude strings that are already present in the
parent language in order to reduce library and executable size. For example
if es
already includes the string "archivo" there is no reason for your
translation to es_mx
to include it, too. You can tell poconvert.rb
to
exclude strings matching another localization like so:
./poconvert.rb msgfmt <language_cc_ll.po> --baselang=<other-language_cc_ll.h>
Although we have provided tools to allow you to work in languages other than
English, we can only accept PO's in the repository that have English msgid
fields. It's easy to convert your PO back to English:
./poconvert msgfmt <language_cc_ll.po>
./poconvert msgunfmt <language_cc_ll.h>
The first command converts your non-standard PO into a Tidy Language Header file, and the second will create a fresh, new PO file from the header that you've just created.
If Tidy's POT changes, e.g., new strings are added, new comments, etc., the simplest way to update your PO is to convert it to a header (which normalizes it to the latest Tidy standard), and then convert the header to a new PO again.
./poconvert msgfmt <language_cc_ll.po>
./poconvert msgunfmt <language_cc_ll.h>
It goes without saying all help is appreciated. We need to work together to make Tidy better!