Help:Translations:Bugs
Handling translation bugs
When translation problem is identified, you need to identify the source of the problem. It could be a problem of translation, problem of packaging or problem of the source code. Before fixing or reporting the bug, you need to identify the source of the problem: Identify a package where the string belongs, identify the exact location of the string in the po file, and find proper way to fix it.
Mapping of strings in application to visible strings is not straightforward: string you see may be composed from several particular strings in po file or even from several packages. Finding the source of the problem needs some work. Additionally, SUSE offers some special features, that allow to import fixes from upstream, so there is no reason to fix things fixed in the upstream manually.
Steps to report and fix translation problem
- Identify type of problem (translation, code, packaging)
- Identify translation domain and string
- Assign domain to package
- Select a correct way to report (downstream, upstream, request a translator work)
- Use a correct bug tracker
All these steps will be described below.
Relation between different names of translation
Translation domain
Translation domain identifies the translation project. It is equal to base name of installed .mo files.
Lang package name
Lang package name is most often derived from the name of the source package. It can be different from translation domain, but in most cases the name is similar, just there are differences in numbers identifying version or differences in case.
Package name
Package name can be also derived from the source package name, but in case of libraries, the name is different.
Source package name
It is a name of the source project. More packages (including lang package) can have a the same source package.
Identify type of problem
Each translation problem could have several sources. Each source needs a different way to handle:
- translation: Missing, incorrect or incomplete translation. Bug will need to be reported to the translation maintainer or co-ordinator (upstream or SUSE). Additional steps may be needed to get the string back to package in your system.
- code: The code lacks support for translation, support for translation is not working or it is incomplete. Also situation where application joins sentence from words using bad inflexion, situations, where the same English string needs different translation in different contexts (and po file does not allow it), situations, where correct translation is mangled by the application are code problems. Also situations, where English text has a mistake, is a code problem.
- packaging: Translation exists, also code is correct, but the package with translation files is not delivered to your system, or it is not automatically installed when it should be.
Sometimes it is not trivial to identify the correct source of the problem, and you need to apply some heuristics. In some cases, using a simple inspection cannot decide, and you will need to ask a package maintainer to look into the problem.
Simple guesses
- The string is translated incorrectly (misspelled etc.) => translation (nearly sure)
- The string is somehow mangled in a mechanical way (e. g. accented characters are lost or mangled) => code (nearly sure)
- The same string is OK (and not equal to English string) in other languages. => missing or incomplete translation (sure)
Quick checks for most often source of problems
All strings are English only in all languages:
- Check whether -lang package related to untranslated package is installed.
If not => package collection issue (package is missing on medium or installation image), packaging issue (missing language Supplements)
- Check whether LANG variable is set properly, and LC_MESSAGES and LC_ALL are not set improperly.
If yes => Your system is misconfigured, or very bad things happened in the system setup.
Generic texts (OK, Cancel) are in English, but the application itself is translated
- Check whether -lang package related to the GUI toolkit of your application (e. g. gtk3-lang) is installed.
If not => package collection issue (package is missing on medium or installation image), packaging issue (missing language Supplements)
Other languages are OK, but in my language the application is in English only
If yes => missing translation issue
The application very probably lacks translation for your language, or it is incomplete.
You will have to locate string in po/pot file, and the ask for translation.
One string is consistently missing in all languages
If yes => Here are two possible sources of this problem:
- Upstream added this string as new just before release and translators did not have enough time to translate. => Upstream translation issue.
- There is a programming issue affecting translatability of the string.
- There is a SUSE specific patch that adds this string, but a mechanism for its translation is missing. => SUSE packaging issue.
See lower how to discriminate between these two cases.
I see the string differently in the mo file using msgunfmt, but not in the application.
Please check also /usr/share/locale-bundle and /usr/share/locale-langpack before doing deeper research. String there take precedence.
Identify translation domain and string
If you suspect that the source of the problem exists somewhere in the translation files, you will have to assign the string in your application to the exact message in the translation file. Or files, because one string visible in your application can be composed from several parts that can even come from several different translation domains.
Once you assign the string to the package, you will be able to direct your report or fix to the correct target.
There is no simple and straightforward method to complete this work. You can start with simple and fast heuristics, and if they fail, try more sophisticated and more exact methods.
String decomposition heuristics
String in the translation message can be different from the string you see. There is no simple way to decompose string to messages. But in some cases you can guess using a simple heuristics.
You can apply these heuristics before doing string look-up, or in situation, when first look-up fails.
Replace numbers by %d
If you see a number in the message, it is probably represented by %d.
Example: "There are 2 open files." => "There are %d open files."
Replace "-ing" by %s
Sometimes a sentence has a "variable" word, most often represented by gerund.
Example: "Error while reading." => "Error while %s." + "reading"
Split on ":"
Colon often represents separator between string from application and string (often error) from library.
Example: "Read error: No such file or directory" => "Read error: %s" + "No such file or directory"
Fast heuristics
String belongs to the same package and domain as the application itself
This is the simplest heuristics, which works for high percentage of strings. Simply look into the pot/po file of package in question. If you are lucky one, the string is there in exactly the same context as you need.
Example: All checks for strings in gnome-control-center should first check gnome-control-center pot/po files.
String belongs to the toolkit
If string in question is a generic string (e. g. "OK", "Cancel", "Files") and if you cannot find the string in the application pot/po file, you could see into the GUI toolkit pot/po file (for example gtk3, glib2 etc.)
Example: "OK" and "Cancel" strings in the gnome-control-center belongs to gtk3 pot/po files.
String belongs to the plugin
Some application can be extended with plugins. The plugin can have a GUI fully integrated to the application, but strings from the plugin implementation belong to a different domain.
Example: eiciel implements ACL and extended attributes in nautilus. However these functions are fully integrated into nautilus, you should check for all strings related to ACL into eiciel pot/po file.
String belongs to the library used
Libraries often contain strings specific to particular functions, and especially error messages. If you are searching for a string in the implementation of a particular function, you should look into providing libraries.
Example: Tools for CIFS/SMB can display strings from samba libraries. You should check samba pot/po files especially for error messages.
Searches
Search for string in the installed locale files
This easy and fast method can provide fast guess, but if the string is not translated in any language, it can easily fail to find anything. It can also provide many false matches for short generic strings.
grep -l -r "{string in question}" /usr/share/locale*
Alternative version (clean output, needs longer time to get first output):
grep -l -r "{string in question}" /usr/share/locale* | sed 's:.*/::;s/\.mo$//' | uniq -d
The filename part (without the trailing mo) is your translation domain. If you see only a single domain match, you are done. You very probably located your string.
Pros: Very fast
Cons: Often false negatives and often false positives
Search for string in the live system
This method needs a lot of machine time, and it often provides many false matches. But it can find the string if all other methods fail.
grep -l -r "{string in question}" /*bin /etc /usr /opt
If it finds a good candidate, then assign it to the package:
rpm -qf {file}
Pros: Can find string not tagged for translation.
Cons: Very slow. Often false positives.
Analytic methods
If the fast method fails, analytic methods can always find your string.
strace
Strace is a common tracing tool. You can use it to get a list of all translation domains that were attempted to access. It is available in the main repository.
Scan for all locale related file that were attempted to open (together with results):
strace -f -o strace.log {command you want to analyze} grep 'open.*locale' strace.log
You see all unsuccessful attempts here. There are harmless as long as the sequence of failures ends by a success.
Scan for all domain names that were attempted to open:
strace -f -o strace.log {command you want to analyze} sed -n 's:^.*open.*/locale.*/\([^/]*\)\.mo.*$:\1:p' strace.log | sort -u
Note: Application can run a bit slower while it is traced with strace.
Example:
test@test:~> strace -f -o strace.log gnome-clocks test@test:~> grep 'open.*locale' strace.log 4336 open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 4336 open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3 4336 open("/usr/lib/locale/cs_CZ.utf8/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = 3 4336 open("/usr/lib/locale/cs_CZ.utf8/LC_MEASUREMENT", O_RDONLY|O_CLOEXEC) = 3 ... 4336 open("/usr/share/locale-bundle/cs.utf8/LC_MESSAGES/libgweather-locations.mo", O_RDONLY) = -1 ENOENT (No such file or directory) 4336 open("/usr/share/locale-langpack/cs/LC_MESSAGES/libgweather-locations.mo", O_RDONLY) = -1 ENOENT (No such file or directory) 4336 open("/usr/share/locale/cs/LC_MESSAGES/libgweather-locations.mo", O_RDONLY) = -1 ENOENT (No such file or directory) 4336 open("/usr/share/locale-bundle/cs/LC_MESSAGES/libgweather-locations.mo", O_RDONLY) = 25 test@test:~> sed -n 's:^.*open.*/locale.*/\([^/]*\)\.mo.*$:\1:p' strace.log | sort -u atk10 desktop_translations gdk-pixbuf glib20 gnome-clocks gnome-desktop-3.0 gtk30 gtk30-properties json-glib-1.0 libc libgweather-locations pulseaudio
wrap-gettext
wrap-gettext works on the higher level, and it reports all gettexts use to you. It is part of the trace-wrappers package, and currently resides only in the OBS home:sbrabec repository. You can use 13.1 binary package for SLE12.
Using this utility, you can get an insight to the string composition inside the application. In difference to strace, you can see each string look-up here. But you cannot see file look-ups like you can do with strace.
Scan and display on console:
wrap-gettext {command you want to analyze}
This form is useful when you want to see particular dialog while being composed. Hint: Enter several Return characters as separator, and the roll console back.
In all other situations, you would prefer logging to file.
wrap-gettext {command you want to analyze} 2>wrap-gettext.log
Note: You can see a strange 0004 or ^D character. It works like an internal separator between context and the string contents, and it is used in strings using msgctxt tag (in preference to |).
Example:
test@test:~> wrap-gettext gnome-clocks 2>wrap-gettext.log test@test:~> less wrap-gettext.log WRAP: bindtextdomain("gnome-clocks", "/usr/share/locale") = "/usr/share/locale" WRAP: bind_textdomain_codeset("gnome-clocks", "UTF-8") = "UTF-8" WRAP: textdomain("gnome-clocks") = "gnome-clocks" WRAP: bindtextdomain("glib20", "/usr/share/locale") = "/usr/share/locale" WRAP: bind_textdomain_codeset("glib20", "UTF-8") = "UTF-8" WRAP: textdomain("(null)") = "gnome-clocks" WRAP: dcgettext("(null)", "", LC_MESSAGES) = "" WRAP: dcgettext("glib20", "The unique identifier for the application", LC_MESSAGES) = "The unique identifier for the application" ... WRAP: dcgettext("gtk30", "keyboard label|F1", LC_MESSAGES) = "keyboard label|F1" WRAP: dcgettext("gtk30-properties", "Standard cursor type", LC_MESSAGES) = "StandardnĂ typ kurzoru" WRAP: dcgettext("gtk30-properties", "Cursor type", LC_MESSAGES) = "Typ kurzoru" WRAP: dcgettext("gtk30-properties", "Display of this cursor", LC_MESSAGES) = "ZobrazenĂ tohoto kurzoru" WRAP: dcgettext("gtk30-properties", "Display", LC_MESSAGES) = "ZobrazenĂ" WRAP: bindtextdomain("pulseaudio", "/usr/share/locale") = "/usr/share/locale" WRAP: bind_textdomain_codeset("pulseaudio", "UTF-8") = "UTF-8" WRAP: dcgettext("pulseaudio", "%0.1f MiB", LC_MESSAGES) = "%0.1f MiB" WRAP: dcgettext("pulseaudio", "%0.1f KiB", LC_MESSAGES) = "%0.1f KiB"
Important: If the string does not appear in the wrap-gettext log, it means, that it is not properly marked for translation.
watch-gettext
Watch-gettext works on the tool very similar to wrap-gettext. It wraps all gettext calls and displays helpers to visualize string origin. It currently resides in the M17N OBS repository.
The utility prefixes each translatable string with a number. It also writes a log (pseudo-po file) with those numbers. If you want to identify any string, just run application inside the watch-gettext wrapper, check the prefixed number, and then look into the log. You will see origin of the string.
Using this utility, you can quickly get an insight to the string composition inside the application. You can see each string composition directly.
Scan and display on console:
watch-gettext {command you want to analyze}
It will write a pseudo-po file with a log of all accesses, and a reference numbers you see in the application.
String verification
Sometimes your string is too generic and you have many matches and you are unsure about the correct match. Here is a simple way to verify it:
msgunfmt /usr/share/{locale_dir}/{language}/LC_MESSAGES/{domain}.mo -o test.po
Now edit test.po and add some gibberish characters to your string.
Then do as root:
# Save original translations. sudo mv /usr/share/{locale_dir}/{language}/LC_MESSAGES/{domain}.mo /usr/share/{locale_dir}/{language}/LC_MESSAGES/{domain}.mo.save # And install our one. sudo msgfmt test.po -o /usr/share/{locale_dir}/{language}/LC_MESSAGES/{domain}.mo
locale_dir can be "locale", "locale-bundle" or "locale-langpack" domain is the package translation domain. In most cases it is equal to the lang package name with possible different version specification at the end.
Then restart your application. You should see the gibberish characters in your string.
You confirmed that you found the correct string!
Now revert the original translation.
# Save original translations. sudo mv /usr/share/{locale_dir}/{language}/LC_MESSAGES/{domain}.mo.save /usr/share/{locale_dir}/{language}/LC_MESSAGES/{domain}.mo
Example:
test@test:~> msgunfmt /usr/share/locale-langpack/cs/LC_MESSAGES/gnome-clocks.mo -o gnome-clocks.po # Mangle msgstr "Start" to msgstr "Staqqqrt" test@test:~> gedit gnome-clocks.po test@test:~> sudo mv /usr/share/locale-langpack/cs/LC_MESSAGES/gnome-clocks.mo /usr/share/locale-langpack/cs/LC_MESSAGES/gnome-clocks.mo.save root's password: test@test:~> sudo msgfmt gnome-clocks.po -o /usr/share/locale-langpack/cs/LC_MESSAGES/gnome-clocks.mo # And now you should see "Staqqqrt" instead of "Start" test@test:~> gnome-clocks test@test:~> sudo mv /usr/share/locale-langpack/cs/LC_MESSAGES/gnome-clocks.mo.save /usr/share/locale-langpack/cs/LC_MESSAGES/gnome-clocks.mo
Assigning domain to package
Assigning translation domain to package is the last step of your work.
If you know -lang package name or library package name and need the source package name (e. g. for reporting purposes):
- -lang package could have a different name than the package with problems. The most probable name can be constructed by:
rpm -qi {package}
Then search for "Source RPM". Get the base of the name, add "-lang", and you got most probable lang package name.
Example:
Translation is missing for libgtk-3-0.
rpm -qi libgtk-3-0
You will see somethere in the output:
Source RPM : gtk3-3.10.4-12.1.src.rpm
=> Corresponding source package is (surely) gtk3, and lang package name will be (probably) gtk3-lang.
This rule for lang package name is not 100% valid. If you need a lang package name, and you fail to find it, you need look at the source rpm spec file.
Translations in desktop, xml and similar files
desktop files
Translations in .desktop, files are handled in a special way in SUSE. There are two completely separated ways to get strings into packages:
- Using macro %suse_update_desktop_file in the spec file collects all translations into the desktop-translations package and also desktop-translations.pot in the LCN and a desktop environment with a SUSE-specific patch using desktop-translations. Such packages can get string fix from the desktop-translation project in the LCN.
- Standard upstream-aware way that gets translations directly from the desktop files. Such packages can get translation update only in the build time using e. g. translation-update-upstream (but not translation-update).
XML and other similar files
Translations in XML and other similar files in some project may be hard-embedded into the file .desktop files. Such files contain translations for all languages in a single file. If you need a fix in a such file, it can get translation update only in the build time using e. g. translation-update-upstream (but not translation-update).
Hopefully most XML files are now translated in a better way: tags that should be translated are prefixed by "_" character, and the XML file is the preprocessed by the code in the run time. Translations for such XML files come from a standard gettext files and can be updated in all standard ways.
Reporting bugs
Package collection issue
This problem is caused by missing -lang package in the installation repository or in the image you are using.
Reporting:
Report it to person who maintains the package collection or the binary repository.
Report it only once at all and list packages that are affected.
Fix:
Fix is done by medium or repository by adding all missing packages.
Important:
It makes sense to continue testing only for one well covered language and for one string per package. Stop further testing of your product until this problem is fixed! It is a waste of your work. This bug nearly always affects all languages.
Packaging issue
If the corresponding -lang (or bundle-lang) package is available but not installed:
Checks:
- Check that you selected your language support in YaST.
- Check that YaST can see the needed lang package.
Reporting:
- Report it to the SUSE package maintainer. Report it only once per package.
- If it is a problem of the installation image (e. g. live CD/DVD), report it to the image maker. It is probably a package collection issue.
Fix:
The package probably does not properly use %lang_package, %find_lang and %files -f %{name}.lang macros.
Notes:
- Some SUSE products use per-language translation bundles (bundle-lang-{package_set}-{language}). They provide the same files like particular lang packages.
Important:
It makes sense to continue testing only for one well covered language. Stop further testing of your product until this problem is fixed! It is a waste of your work. This bug nearly always affects all languages.
Code issue
Code issues include all types of problems in the source code itself:
- The string in question is not properly marked for translation, e. g. _("{string}"), N_("{string}") or ...gettext("{string}"). There can be defined more macros, it is convenient to use one upper case letter and underline.
- The string is marked for translation, but it use a bad type of gettext call.
- The string is marked for translation, but code uses invalid context (bad domain, call before gettext initialization, etc.)
- The string is properly marked for translation, but the file is not included to POTFILES.
- The technical part of the code is correct, but the string does not follow translatability rules, and it cannot be translated to some languages e. g. due to inflexion.
- The English string is a homonym, and a context needs to be added to translate it correctly to other languages.
- SUSE package adds a patch with new string, but the package does not add support for its translation (the project for patch translation is called gnome-patch-translation).
Code issues are reported either to the upstream (as a code problem), or to the SUSE package maintainer. Problems in SUSE patches are always reported to the package maintainer.
Translation issues
Final assigning of string
Before reporting a translation issue, you need to do a final location of the string. Unpack the source package and look into it. If the string is located in the upstream tarball, it is an upstream issue. If the string is located in one of SUSE patches, it is a SUSE issue.
Generic rules
It makes no sense to report translation bugs to the package maintainer. Package maintainer cannot fix it (without help of native speakers).
The translation is incorrect
This is an easy case. You need to find a translation maintainer of the string and report the problem there.
The translation is missing or incomplete
It makes no sense to report these issues. Translator team simply does not have enough power to translate, and repeatedly claiming it does not make things better.
If you really need to fix this issue, the only way for fix is finding a translator, join the translation project and make it complete.
String is SUSE specific patches
If the string is located in a SUSE patch, package needs a special care. Package maintainer should use gnome-patch-translation for adding possibility to translate new strings. (In contrast to its name, the tool can support more than GNOME.) Packager maintainers should follow its README.
Translation sources
SUSE uses several translation sources:
- SUSE LCN Project handles translations mostly for packages that are SUSE specific. It also contains several packages no more maintained in the upstream.
- Upstream packages is the most common source of strings. It uses strings as they come from upstream.
- Update tools provide alternate way to deliver translation updates to users, but they use the same translation sources as above (plus latest upstream snapshots).
Depending on the translation source, you have to select correct way to report the bug.
LCN project bugs
If you identify LCN as the primary translation source, report it to:
- openSUSE: Person mentioned as "Last translator".
- SLE: Report it to Novell Bugzilla for your product, component Translations.
Upstream bugs
If the package has a live upstream, translation bugs are reported to the upstream:
Larger project (GNOME, KDE) has its own translation projects, and the bug is reported to the translation project. The bug is reported to the native speaker, who is a final authority for its fix. If you want to do more work that a single fix, it is useful to join the translation team.
Small project which have no translation project have no native speakers directly involved to the development. You are reporting and you are responsible that your fix is correct.
Before reporting to the upstream, you have to check, whether the upstream-maintained version still contains the string in question:
- Find the latest upstream pot file and check for your string. Note that some projects have two or more branches with maintained translations. In such case you should check all of them.
- String is here. => The problem can be solved in the upstream.
- String is not here. => Problem has to be solved by SUSE package maintainer and a SUSE translator as a special case. You will have to extract such dropped strings from the pot file, and package maintained will have to add special merge for them.
GNOME
GNOME upstream has two level of support:
- GNOME Bugzilla Infrastructure/l10n is a correct place for reporting GNOME translation bugs. It is a volunteer project, so it makes no sense to report missing translations.
- Joining the GNOME Translation Project is highly recommended for regular work on translation. Translators will get a commit permission for translations.
GNOME L10N is a portal for read-only access to the latest translations.
Upstream cooperation
- If the project has a live upstream, never fix upstream bugs inside SUSE. Such fix will be lost with the next SUSE version, or you will get lots of conflicts.
- If you want to work on translation that has a live upstream, you should be in connection with the upstream translation team.
Bug is fixed in upstream or LCN. What now?
Now suppose that your bug is finally fixed in the upstream or the new translation was fixed in the LCN.
The processes in SUSE can provide a lot of help with the import of the fix back, but in some cases it needs some work.
- If the package translation project resides in LCN, and your product is in pre-release stage, you don't have to do anything. There are translation rounds, and after the end of the translation round, the translation should be imported to packages, either directly by package maintainers, or indirectly by the translation-update-upstream project.
- If the package is included to the translation-update-upstream project, and the fix appeared in a live upstream repository, fix is also automatically imported during the next translation collection. (You can identify such package by translation-update-upstream command in the source spec file.)
- If the package is not included to the translation-update-upstream project, you need to open a bug and assign it to the package maintainer. Package maintainer will pick the latest translation, and submit the package.
- If your SUSE version is already released, there is a special translation-update package. It can provide translation update without rebuilding of any package with code. This way is used especially after release.
Notes for package maintainers
How translation update packages work?
As a package maintainer, you will often have to update translations. Translations typically come with the upstream project, located in the main tarball in the po directory. As the translation work is often delayed compared with the code, you will be often requested to update translations. To simplify this work, there are several special tools in SUSE.
translation-update
translation-update is a simplest way to update. It can deliver latest translations in install time without rebuild of any package. This feature is allowed by a SUSE-specific definition of override directory in glibc. The cost for that is a double installation of translation files for all users.
Important: If a mo file is found in the update directory, the original mo file is not read at all. This is the behavior defined in the glibc patch. Only complete translations are possible in translation-update package.
This package contains three tarballs:
translation-update-from-translation-update-upstream-*.tar.bz2
Tarball generated by the translation-update-upstream supplementary scripts. See below. Don't edit it manually!
translation-update.tar.bz2
Manually created package with translation updates. Nowadays it is probably empty.
translation-update2.tar.bz2
Manually created package with translation hot fixes. Strings here take precedence over all other strings. Nowadays it is probably empty.
translation-update-upstream
translation-update-upstream is a package that can provide build-time updates of translation. Each package supporting it must have a translation-update-upstream command in its %prep stage:
%prep %setup -q # Here you unpack everything that comes from upstream # Here apply all patches that come from upstream and bring new upstream strings translation-update-upstream # Here apply all other patches
translation-update-upstream provides strings for compile time. The updated translation-update-upstream has to be available in the time of compilation of the package, and strings will end in the package po directory, and -lang sub-package after compilation.
Important: Each package that need translation updates has to be listed at least once in translation-update-upstream package, one of files named *.tlst. Each line defines one update URL.
There are two levels of translation update sources in .tlst files. Sources marked with mandatory tag are included completely into the package and take absolute precedence over all other translations. Sources that are not marked with that tag are compared, and policy ânewer translation winsâ is applied.
The translation-update-upstream has several supplementary scripts that are called by its maintainer:
Supplementary script upstream-collect.sh
This is the main script. Scripts collect strings from all sources defined in .tlst files, compares them with the strings actually available in the package, and finally creates an update tarballs.
Supplementary script translation-update-upstream-to-translation-update.sh
It is not always possible to fulfill the requirement of translation-update-upstream, and provide it in the compile time. That explains purpose of this script. It goes through all strings and all supported packages, and detects packages will not be rebuilt with the updated translation-update-upstream. The output of this script is a tarball. Package maintainer has to package this tarball as a part of translation-update package (i. e. copy it to another package).
This script is mainly useful for service packs and online updates.
Supplementary script check-translation-completeness.sh
This script just makes translation statistics of all strings in all packages.
Supplementary script configuration upstream-collect.conf
This is a configuration file for upper mentioned supplementary scripts. It defines sources of packages in the release.
Supplementary script create-tlst-step*
These scripts needs a special environment (complete distribution RPM tree mounted in the file system) and compares po files in all packages with po files in and upstream repositories (currently only GNOME GTP) and searches for matches. As a result, it generates a .tlst file with a list of upstream sources (currently only upstream-gnome_gtp.tlst).
gnome-patch-translation
gnome-patch-translation is a tool that makes possible to translate strings in SUSE specific patches. These strings are marked in the code for translation as all other strings, but without any furher effort they would never reach translators.
This tool makes possible to collect such strings, merge them to one file that can be uploaded to LCN. Translators then upload translations back, and these translations are imported during the package build.
Except the initial work on the package, all this work happens without any work of the package maintainer. The maintainer of the gnome-patch-translation package will import translations to the SUSE for all such packages at once.
gnome-patch-translation maintainer should follow its HOWTO.
The %prep stage should look (together with translation-update-upstream:
%prep %setup -q # Here you unpack everything that comes from upstream # Here apply all patches that come from upstream and bring new upstream strings translation-update-upstream gnome-patch-translation-prepare # Here apply patches that introduce new SUSE specific strings and also all other patches gnome-patch-translation-update
The tool compares pot files between these two runs and finds differences. While calling supplementary scripts, these strings are collected.
Important: Each package that has custom strings in patches has to be listed in gnome-patch-translation package, file gnome-patch-translation.conf (and in corresponding LCN) of the SUSE product in question.
Tips for advanced use of gettext utilities
Join two po files into one
While joining two po files into one, you have to decide, what to do with translations that differ in these files.
Join, in case of different translations use the first found:
msgcat --use-first file1.po file2.po -o joint.po
Second method join files with ârejectsâ whenever strings differ:
msgcat file1.po file2.po -o joint.po
In this case, all unique messages or messages translated identically in both projects will remain the same, but messages translated differently will include both instances separated by a special string "#-#-#-#-#", and the whole string will be marked as fuzzy.
Filtering po files
If you want to completely remove messages marked as fuzzy:
msgattrib --no-fuzzy old.po -o new.po
If you want to completely remove messages marked as obsolete:
msgattrib --no-obsolete old.po -o new.po
Find unique messages
If you want to find messages that exist only in one of compared po files:
msgcomm --unique file1.po file2.po -o unique.po
Sometimes you want to find strings that are unique in file2.po. You can do it by combining of two tools:
msgcat --use-first file1.po file2.po -o bothfiles_tmp.po msgcomm --unique bothfiles_tmp.po file1.po -o unique-in-file2.po rm bothfiles_tmp.po