1# Translating mypaint 2 3[![Translation status](https://hosted.weblate.org/widgets/mypaint/-/svg-badge.svg)](https://hosted.weblate.org/engage/mypaint/?utm_source=widget) 4 5MyPaint uses WebLate for its translations. 6You can get involved at <https://hosted.weblate.org/engage/mypaint/>. 7 8That might be all the information you need 9if you just want to help ensure that MyPaint 10is correctly translated into your language. 11 12# Information for coders and maintainers 13 14We use [GNU gettext][gettext] for runtime translation of program text. 15 16Please note that there are two projects that need translating for the 17MyPaint app: 18 19* libmypaint, the brush engine library that MyPaint uses. 20* MyPaint itself. 21 22both projects are exposed on WebLate. 23 24The rest of this document covers translating 25the MyPaint application itself, minus libmypaint. 26 27## Making strings translatable 28 29This section gives an overview of how to make strings translatable 30in the source code. For in-depth technical details of the workings, 31of gettext, refer to [its manual][gettext]. 32 33Strings that need to be translatable have to be used as arguments in calls 34to particular translation functions, also referred to as "macros" 35(preprocessor macros is a standard way of using gettext in C, the python calls 36used are not actually macros, but rather functions or function aliases). 37The purpose of these calls are twofold: they make it possible to extract the 38translatable strings and related information from the source code _and_ they 39perform the actual translation lookups at runtime. 40 41> **Don't use aliases of the translation functions!** 42> Even though the _lookup_ will still work, the _extraction_ 43> process is based on keywords, and cannot deduce aliasing, resulting 44> in the strings not being extracted to the translation template. 45 46### Basic translation: `_(message)` 47 48The `_` function is an alias of the standard gettext function, and takes 49the string _literal_ of the message to be translated as its only argument. 50If there is a comment block immediately preceding the **first line** 51of the _argument_, that comment will be extracted as well to provide 52information about the string to translators. 53 54When extracted, the argument string will appear as a msgid field in the translation 55files, in conjunction with a set of extracted comments and source code locations. 56 57Most of the time the `C_` function should be favored over `_`, when creating new strings, 58but be careful about replacing existing `_(...)` calls with `C_(...)`. 59See the following sections for details. 60 61### Context-specific translation: `C_(context, message)` 62 63The `C_` "macro" takes a context string literal in addition to the message 64string literal. The context has two purposes: it can provide useful 65information to the translators about how the string is used and it makes 66it _possible_ to have different translations for the same message string 67(when an identical message literal is used in different places). 68 69For more information, see [the relevant section in the gettext manual][gettext_ctx] 70 71Be careful about changing existing calls to `_` with calls to `C_` 72just to add contextual information when there is no need for disambiguation. 73The reason is that such changes will mark existing translations of that message 74as fuzzy - and such translations will not be used until the fuzzy flag has been 75removed (usually by a translator reviewing changes). 76If you just want to add documentation, use a translator comment. 77 78### Adding translator comments 79 80An important thing to know about _translator comments_ is that they are only 81extracted when preceding the line that the string literal of the _message_ 82**starts on**. See the examples below for how comment placement matters. 83 84<details> 85<summary>Examples</summary> 86 87``` 88# This comment will be extracted 89translated = _("my message") 90 91# This comment will be extracted too 92translated = C_("context of my message", "my message") 93 94# Both of these comment lines will 95# be extracted; they form a block. 96translated = C_("context of my message", "my message") 97 98# This comment will NOT be extracted! 99translated = _( 100 "this message is really long, and has been placed on its very own line" 101) 102 103translated = _( 104 # But this comment WILL be extracted 105 "this message is really long, and has been placed on its very own line" 106) 107 108translated = C_( 109 # This comment precedes the CONTEXT line and will NOT be extracted! 110 "context of my message", 111 "my message" 112) 113 114translated = C_( 115 "context of my message", 116 # This comment precedes the MESSAGE line and WILL be extracted 117 "my message" 118) 119 120``` 121</details> 122 123### Using variables in message strings 124 125When the translated strings contain variables, use python brace format: 126``` 127translated = C_( 128 "shmoo-counter: status message", 129 # TRANSLATORS: We have to use pounds for reasons of historical accuracy 130 "Counted {num_shmoos} shmoos, weighing a total of {total_weight} pounds." 131 ).format(num_shmoos=len(shmoos), total_weight=sum([s.weight for s in shmoos])) 132``` 133 134_Never_ stitch together translated fragments with variables - it will always 135make translation very difficult. For many languages doing it may even make it 136impossible to produce translations with correct grammar, due to the order of 137arguments being impossible to change. 138 139## After updating program strings 140 141After adding or changing any string in the source text which 142makes use of the gettext macros, you will need to manually run 143 144 cd po/ 145 ./update_potfiles.sh 146 147 ./update_languages.sh 148 149and then commit the modified `po/mypaint.pot` & `po/*.po` too, 150along with your changes. 151 152The `.pot` file alone can be updated by running 153just the first command, 154if all you want to do is compare diffs. 155 156The `update_metadata.sh` script does not need to be run on a regular basis. 157It is just a convenience for generating generic headers for new language files 158and for updating the version field of existing language files. 159 160# Information for translators 161 162## New translation (manual) 163 164Start by putting a new stub `.po` file into this directory. 165 166To make such a file you can 167copy the header from an existing `.po` file 168and modify it accordingly. 169 170Unless there are several country-specific dialects for your language, 171the file should be named simply `ll.po` 172where "ll" is a recognized [language code][ll]. 173 174If there are several dialects for your language, 175the file should be named `ll_CC.po` 176where "CC" is the [country code][CC]. 177 178Before you can work on it, 179you will need to update the `.po` file 180from the most recent `.pot` template file 181generated by the developers. 182 183## Update translation (manual) 184 185Before working on a translation, 186update the `po` file for your language. 187For example, for the French translation, run: 188 189 update_languages.sh fr.po 190 191## Use/Test the translation 192 193After modifying the translation, 194you can run MyPaint in demo mode to see the changes: 195 196 python setup.py demo 197 198If you want to run MyPaint with a specific translation on Linux, 199here are two ways of doing so: 200 201You can either use the LANG environment variable 202like this (the locale needs to be supported): 203 204 LANG=ll_CC.utf8 python setup.py demo 205 206where "ll" is a [language code][ll], and and "CC" is a [country code][CC]. 207 208If you don't have to locale of the language you want 209to test installed, you can use the LANGUAGE variable 210instead: 211 212 LANGUAGE=ll_CC python setup.py demo 213 214> You don't have to supply the country code (CC) if you 215> don't need to disambiguate multiple dialects. 216 217> When using `LANGUAGE` without having the locale installed, 218> some strings that are not part of MyPaint will not be translated. 219> For example, button strings in file chooser dialogs. 220 221To run MyPaint with the original strings, for comparison, 222you can use the `LC_MESSAGES` variable like this: 223 224 LC_MESSAGES=C python setup.py demo 225 226## Send changes (manual) 227 228Before you send your changes, please make sure that 229your changes are based on the 230current development (git) version of MyPaint. 231 232We prefer changes as [Github pull requests][PR], 233but if you do not know git you can also [open a new issue on github][NEW_ISSUE] 234and attach either a unified diff or the new/updated .po file to it. 235 236## Weblate 237 238Weblate provides a browser-based interface for adding, editing 239and updating translations. It's a very good way to provide 240translations without having to worry about the technical details. 241 242If you are interested in keeping the translations up to date, 243please subscribe to the MyPaint project on WebLate: 244<https://hosted.weblate.org/accounts/profile/#subscriptions>. 245 246------------------- 247 248[gettext]: http://www.gnu.org/software/hello/manual/gettext/ (Official GNU gettext manual) 249[gettext_ctx]: https://www.gnu.org/software/gettext/manual/gettext.html#Contexts (gettext manual section on message contexts) 250[ll]: http://www.gnu.org/software/hello/manual/gettext/Usual-Language-Codes.html#Usual-Language-Codes ("ll" options) 251[CC]: http://www.gnu.org/software/hello/manual/gettext/Country-Codes.html#Country-Codes ("CC" options) 252[PR]: https://help.github.com/articles/using-pull-requests/ 253[NEW_ISSUE]: https://github.com/mypaint/mypaint/issues/new?title=Manual+translations+for:+LANGUAGE&body=New%2Fupdated+translations+for+%2E%2E%2E 254