Changes

Jump to: navigation, search

Coding for translation

4,766 bytes added, 16:37, 4 May 2013
m
Add the reference to the file
[[Category:Developers/General]]
==Introduction==
GRAMPS Gramps has always been internationalized (see
http://gramps-project.org/2006/04/looking-back-over-5-years).
Therefore, all strings meant
for the user should always be flagged for translation.
In order to be considered for inclusion in the offical GRAMPS Gramps release, any piece of code must support internationalization. What this means is that the Python module must support [[Translating GRAMPSGramps|translations]] into different languages. GRAMPS Gramps provides support to make this as easy as possible for the developer. For enabling, a language code must be set on ''configure.in'' file into ''ALL_LINGUAS'' section.
==How to allow translations==
GRAMPS Gramps is a fully-internationalized application with translations in many languages. All code which presents text to users must provide for that text to be translated. Fortunately, Gramps provides a simple interface (based on the an extension of [http://docs.python.org/3/library/gettext.html gettext interface) to mark strings as being translatable] which makes this fairly painless. First, import alias the gettext function from the intl library.single localization instance: from gramps.gen.ggettext const import gettext GRAMPS_LOCALE as glocale _= glocale.translation.gettextThis statement imports the <code>sgettextgettext</code> function under the name of and aliases it as <code>_</code>. This is the function that both marks the The translation tools treat strings wrapped in _() as translatable and assemble them into catalogs for translation and performs the actual translators to work with; by aliasing it to gettext(), we also enable python to retrieve the translation at runtime. Strings that should be translated should be enclosed as an argument to appropriate for the functionuser's locale.
Example 1:
print _("Hello world!")
In this example, GRAMPS Gramps will attempt to translate the string. If a translation exists, the call to the function will return the translation. If a translation does not exist, the original string is returned. === More complicated translations === In addition to <tt>gettext</tt>, GrampsTranslation offers two more specialized retrieval functions, <tt>ngettext</tt> and <tt>sgettext</tt>.  In some strings, it's necessary to specify different translations depending upon the number of an argument. For example, George Smith and Annie Jones have 1 child George Smith and Annie Jones have 3 children
All strings meantWe'd code that in python as follows:for the user should be always be preceeded with the _ function= glocale.translation.ngettext _(George Smith and Annie Jones have %(num)d child, George Smith and Annie Jones have %(num)d children, n) % {num : n}
In other cases, it's necessary to provide a hint to translators, e.g. _(Remaining names | rest) We're making sure that the translators know that this message id means "what's left" rather than "take a nap". When the file is translated, this is no problem, because the translation doesn't include the hint -- but if the user is working in English, we don't want him to see the hint, so we need to alias _ to sgettext: _ = glocale.translation.sgettext Often you need to combine them. While <tt>ngettext</tt> and <tt>sgettext</tt> can each handle plain strings, neither can handle the other's strings. Fortunately the <tt>intltool</tt> message extractor is pretty stupid, so any function name that ends in either <tt>_</tt> or <tt>gettext</tt> will work. This will work pretty well:  _ = glocale.translation.gettext N_ = glocale.translation.ngettext S_ = glocale.translation.sgettext Obviously you would pass the translatable string to the right function. === Encoding ===String handling can be a bit tricky in a localized environment. Gramps's translation facility will always return Unicode-encoded strings. For as long as it is necessary to support both Python2 and Python3, developers will need to understand Unicode string handling in both versions of the language. If you use non ASCII characters in a string literal the string must be Unicode. '''Don't do this:''' print _(u"Eg, valid values are 12.0154, 50° 52′ 21.92″N") Because the <tt>u</tt> prefix was removed for Python 3.0-3.2. (It was restored in 3.3 for compatibility with 2.7, but it's not necessary.)Instead, put in the first line of the module # *-* coding: utf-u *-*then in the imports section from __future__ import unicode_literalswhich makes all of the literals unicode. Make sure that your editor is set up to save utf-8! ==Into glade file=Glade files===
Just enable the translatable attribute on an XML element.
<property name="label" translatable="no">&lt;b&gt; - &lt;/b&gt; </property>
===Into addons plugins=Non ASCII characters==== If you plan to use non ASCII characters in a string, that shall be translated,do not use escape sequences:  Eg, valid values are 12.0154, 50<code>&amp;</code>#xB0; 52' 21.92"N use instead:  Eg, valid values are 12.0154, 50° 52′ 21.92″N In this case note the unicode characters for deg, min, sec. '''Ensure that your editor is set up to encode the characters in UTF-8!''' ====Accessibility==== In addition to [http://developer.gnome.org/gtk/2.24/GtkWidget.html#id1294298 accelerators], ''[http://developer.gnome.org/gtk/2.24/GtkWidget.html GtkWidget]'' also support a custom <accessible> element, which supports actions and relations. Properties on the accessible implementation of an object can be set by accessing the internal child "accessible" of a ''[http://developer.gnome.org/gtk/2.24/GtkWidget.html GtkWidget]''. See [http://developer.gnome.org/gtk/2.24/GtkWidget.html#GtkWidget-BUILDER-UI GtkBuilder UI]. * Gtk label
from TransUtils import get_addon_translator _ = get_addon_translator()''A [http://developer.gnome.org/gtk/2.24/GtkLabel.html GtkLabel]'' '''with mnemonic support''' will automaticaly generate accessibility keys on linked ''[http://developer.gnome.org/gtk/2.24/GtkEntry.html GtkEntry]'' and ''UndoableEntry'' fields. Remember that Gramps also uses custom widgets like ''StyledTextEditor'' and ''ValidatableMaskedEntry'', which do not always have relation with a ''GtkLabel''.gettext
See [[Addons_Development#Localization|Addon developpement]].* Toggle buttons and Icons on toolbar
==How it works==Gramps often uses ''[http://developer.gnome.org/gtk/2.24/GtkToggleButton.html GtkToggleButtons]'' and alone ''[http://developer.gnome.org/gtk/2.24/GtkImage.html GtkImage]'' (image without label), this excludes blind people and generates a poor interface for accessibility.
See [http://www.gnu.org/software/gettext/manual/gettext.html GNU gettext] and [http://live.gnome.org/TranslationProject/DevGuidelines/Localize%20using%20gettext%20and%20intltool Gnome] provide utilities and a [http://www.gnome.org/~malcolm/i18n/build-changes.html translation framework] (''previously [http://gramps.svn.sourceforge.net/viewvc/gramps/branches/maintenance/gramps20/gramps2/src/build_po build_po] and [http://gramps.svn.sourceforge.net/viewvc/gramps/branches/maintenance/gramps20/gramps2/src/get_strings get_stringsAccessibility]''):* [http://www.gnu.org/software/autoconf/manual/gettext/msginit-Invocation.html msginit] will generate a standard gettext header.* intltool-update will manage template and translations.* intltool-extract will extract translation strings on ''.glade'' and ''.xml'' files, by generating files with ''.h'' extension.
# Generates a new template (gramps.pot), into ''/po'' directory : intltool-update -p===Addons===
* intltool-merge will merge cached translations into External addons often need to provide their own message catalogs.To pull one in files, usethis instead of the usual. from gramps.gen.const import import GRAMPS_LOCALE as glocale _ = glocale.get_addon_translator(__file__).gettextor if you need more than one retrieval function: _translation = glocale.get_addon_translator(__file__) _ = _translation.gettext S_ = _translation.sgettext
# Merges translated strings into desktop fileThe addon translator is another instance of GrampsTranslation, ''root'' directory :so the rules for creating intltool-merge -d po/ data/gramps.desktop.in data/grampstranslatable strings and for retrieving the translated values are the same as for internal modules.desktop
See [[Addons_Development# Merges translated strings into xml file, ''root'' directory : intltool-merge -x po/ data/grampsLocalization|Addons development]] for more details.xml.in data/gramps.xml
# Merges translated strings into key file, ''root'' directory : intltool-merge -k po/ data/gramps.keys.in data/gramps.keys ==How it works==
===Files and directory===We need at least [http://www.gnu.org/software/gettext/manual/gettext.html GNU gettext], then [http://www.gnu.org/software/autoconf/manual/gettext/msginit-Invocation.html msginit] will generate a standard gettext header.
There are two stages Gramps has used different environments according to getting a translation versions for retrieving strings to work. Translations are stored in a <code>.po</code> file that contains the mappings between the original strings and the translated strings, see [[Translating GRAMPS]]. translate:
Translators use a generic file <code>gramps* [[Translation_environment20|2.pot</code> to generate their <code>.po</code> file0.x]]GRAMPS uses a utility that extracts the strings from the source code to build the <code>* [[Translation_environment22|2.po</code> file2. This utility (a perl script called by the command <code>make</code>) examines the source files for strings that have been marked as translatablex to Gramps 3. In the python source, these are the strings enclosed in the <code>_()</code> function calls4.x]]* [[Translation_environment4|Trunk]]
If you want this script There are two stages to take your translatable strings into account, you must add your source file path in the file : <code>po/POTFILES.in</code>getting a translation to work. For this report example, you should add:
... # plugins ===Files and directory src/plugins/AncestorChart2.py src/plugins/AncestorReport.py ... src/plugins/FindDupes.py src/plugins/Leak.py src/plugins/MediaManager.py src/plugins/Myreport.py # <------ src/plugins/NarrativeWeb.py src/plugins/PatchNames.py ...===
In this Translations are stored in a <code>.po</code> filethat contains the mappings between the original strings and the translated strings, see [[Translating Gramps]].  Translators use a generic file <code>gramps.pot</code> to generate their <code>.po</code> file.Gramps uses a utility that extracts the strings from the source code to build the <code>.po</code> file. This utility examines the source files for strings that have been marked as translatable. In the sources python source, these are sorted within each directory or categorythe strings enclosed in the <code>_()</code> function calls.
Note that because strings are extracted by a script from the source file, string constants and not variables must be enclosed in the <code>_()</code> call. In the following example, the extraction script will not extract the string.
At run time, the <code>_()</code> calls will translate the string by looking it up in the translation database (created from the <code>.po</code> files) and returning the translated string.
You can check missing references (not on <code>POTFILES===Add the reference to the file=== We need to also add a reference to this file for generating the translation template.in</code> and <code>POTFILES * [[Translation_environment22#Files_and_directory|2.skip</code>) with the command2.x to Gramps 3.4.x]] /intltool-update -m into <code>/po</code> directory* [[Translation_environment4#Files_and_directory|Gramps 4.0.x, Trunk]]
==Tips for writing a translatable Python module==
===Use complete sentences===
Don't build up a sentence from phrases. Because a sentence is ordered in a particular way in your language does not mean that it is ordered the same way in another. Providing the entire sentence as a single unit allows the translator to make a meaningful translation. Do not concatenate phrases or terms as they will then show up as separate phrases or terms to be translated and the complete sentence may then show up incorrectly, especially in right-to-left languages (Arabic, Hebrew, etc.).
===Use named %s /%d values===
Python provides a powerful mechanism that allows the reordering of %s values in a string. A translator may need to rearrange the structure of a sentence, and it may not match the order you chose. For example:
print "%s was born in %s" % ('Joe','Toronto')
'city' : 'Toronto', 'male_name' : 'Joe'}
In this case, the order of the %s formatters is not important, since the values will be looked up in the dictionary at run time to resolve the value. The translator can reorder the %s formatters, or even remove them without causing any problems.
Note that Python also allows a variation which some people find easier to read:
print "%(male_name)s was born in %(city)s" % dict(
city = 'Toronto', male_name = 'Joe')
 
Some languages are using right-to-left text direction. It is important to use named arguments when there is more than one %s/%d value into a translation string.
===Provide separate strings for masculine and feminine.===
Plurals are handled differently in various languages. Whilst English or German have a singular and a plural form, other languages like Turkish don't distinguish between plural or singular and there are languages which use different plurals for different numbers, e.g. Polish.
Gramps provides a [[Translating_GRAMPSTranslating_Gramps#Plural_forms|plural forms]] support, useful for locales with multiples plurals according to a number (''often slavic based languages'') or for Asian family languages (''singular = plural'').  Note, some locales need singular form with [http://en.wikipedia.org/wiki/Plural#Zero zero] and plural form might be also used in this case.
We need to call module :
We need to call module :
from TransUtils gen.ggettext import sgettext as _
or
from TransUtils gen.ggettext import sngettext as _(if you use ngettext)# not implemented
Translation string will use context, but this will be hidden on user interface.
Translator will see the translation string and a help string without loading program.
Program will only display the string in English or with another locale.
 
===Object classes===
 
Gramps often displays names of primary objects (''Person, Family, Event, etc ...''), for being consistent on displayed strings (also in english!), there is a ''trans_objclass(objclass_str)'' function on TransUtils module.
 
So, when we need to display the primary object name in lower case into a sentence, we can use this function.
 
ex:
from gen.ggettext import sgettext as _
from TransUtils import trans_objclass
 
_("the object|See %s details") % trans_objclass(objclass)
_("the object|Make %s active") % trans_objclass('Person')
 
will display:
 
See ''the person'' details # or See ''the family, the event, etc...'' details
Make ''the person'' active
 
===Genitive form===
 
Genitive (and some other) forms need to modify the name itself into some locales, like Finnish or Swedish.
 
Instead of "free form" text that talks about
e.g.
son '''of %s'''
better would be for example some tabulated format like this:
son: %s
daughter: %s
which doesn't require genitive.
==Textual reports==
Since Gramps-3.2 we are able to select the language for textual reports, see [http://www.gramps-project.org/bugs/view.php?id=2371 this feature].
Currently only available on Ancestor report(3.2.x) and detailed reports (3.3.x).
For providing this option:

Navigation menu