Add transifex system Add entry system for different string entry type, use ruamel for yaml. The Transifex system currently only supports yaml format.
guix-full.manifest
| 17 | 17 | "python-neovim" | |
| 18 | 18 | "python-polib" | |
| 19 | 19 | "python-pyqt" | |
| 20 | + | "python-ruamel.yaml" | |
| 20 | 21 | "python-sphinx" | |
| 21 | 22 | "python-twine" | |
| 22 | 23 | "qt" |
guix.manifest
| 6 | 6 | "python-lxml" | |
| 7 | 7 | "python-polib" | |
| 8 | 8 | "python-pyqt" | |
| 9 | + | "python-ruamel.yaml" | |
| 9 | 10 | "python-sphinx" | |
| 10 | 11 | "python-twine")) |
i18n/offlate_fr.ts
| 3 | 3 | <context> | |
| 4 | 4 | <name>NewWindow</name> | |
| 5 | 5 | <message> | |
| 6 | - | <location filename="../offlate/window.py" line="190"/> | |
| 6 | + | <location filename="../offlate/window.py" line="202"/> | |
| 7 | 7 | <source>The Translation Project</source> | |
| 8 | 8 | <translation>Le Projet de Traduction</translation> | |
| 9 | 9 | </message> | |
| 10 | 10 | <message> | |
| 11 | - | <location filename="../offlate/window.py" line="193"/> | |
| 11 | + | <location filename="../offlate/window.py" line="207"/> | |
| 12 | 12 | <source>Cancel</source> | |
| 13 | 13 | <translation>Annuler</translation> | |
| 14 | 14 | </message> | |
| 15 | 15 | <message> | |
| 16 | - | <location filename="../offlate/window.py" line="194"/> | |
| 16 | + | <location filename="../offlate/window.py" line="208"/> | |
| 17 | 17 | <source>OK</source> | |
| 18 | 18 | <translation>OK</translation> | |
| 19 | 19 | </message> | |
| 20 | + | <message> | |
| 21 | + | <location filename="../offlate/window.py" line="193"/> | |
| 22 | + | <source>Project information</source> | |
| 23 | + | <translation type="unfinished"></translation> | |
| 24 | + | </message> | |
| 25 | + | <message> | |
| 26 | + | <location filename="../offlate/window.py" line="199"/> | |
| 27 | + | <source>Name:</source> | |
| 28 | + | <translation type="unfinished"></translation> | |
| 29 | + | </message> | |
| 30 | + | <message> | |
| 31 | + | <location filename="../offlate/window.py" line="200"/> | |
| 32 | + | <source>Target Language:</source> | |
| 33 | + | <translation type="unfinished"></translation> | |
| 34 | + | </message> | |
| 35 | + | <message> | |
| 36 | + | <location filename="../offlate/window.py" line="203"/> | |
| 37 | + | <source>Transifex</source> | |
| 38 | + | <translation type="unfinished"></translation> | |
| 39 | + | </message> | |
| 40 | + | <message> | |
| 41 | + | <location filename="../offlate/window.py" line="220"/> | |
| 42 | + | <source>Organization</source> | |
| 43 | + | <translation type="unfinished"></translation> | |
| 44 | + | </message> | |
| 20 | 45 | </context> | |
| 21 | 46 | <context> | |
| 22 | 47 | <name>ProjectView</name> | |
| 23 | 48 | <message> | |
| 24 | - | <location filename="../offlate/window.py" line="103"/> | |
| 49 | + | <location filename="../offlate/window.py" line="110"/> | |
| 25 | 50 | <source>Singular</source> | |
| 26 | 51 | <translation>Singulier</translation> | |
| 27 | 52 | </message> | |
| 28 | 53 | <message> | |
| 29 | - | <location filename="../offlate/window.py" line="104"/> | |
| 54 | + | <location filename="../offlate/window.py" line="111"/> | |
| 30 | 55 | <source>Plural</source> | |
| 31 | 56 | <translation>Pluriel</translation> | |
| 32 | 57 | </message> | |
… | |||
| 34 | 59 | <context> | |
| 35 | 60 | <name>SettingsWindow</name> | |
| 36 | 61 | <message> | |
| 37 | - | <location filename="../offlate/window.py" line="254"/> | |
| 62 | + | <location filename="../offlate/window.py" line="298"/> | |
| 38 | 63 | <source>Cancel</source> | |
| 39 | 64 | <translation>Annuler</translation> | |
| 40 | 65 | </message> | |
| 41 | 66 | <message> | |
| 42 | - | <location filename="../offlate/window.py" line="255"/> | |
| 67 | + | <location filename="../offlate/window.py" line="299"/> | |
| 43 | 68 | <source>OK</source> | |
| 44 | 69 | <translation>OK</translation> | |
| 45 | 70 | </message> | |
| 46 | 71 | <message> | |
| 47 | - | <location filename="../offlate/window.py" line="283"/> | |
| 72 | + | <location filename="../offlate/window.py" line="360"/> | |
| 48 | 73 | <source>Email:</source> | |
| 49 | 74 | <translation>Adresse de courriel :</translation> | |
| 50 | 75 | </message> | |
| 51 | 76 | <message> | |
| 52 | - | <location filename="../offlate/window.py" line="284"/> | |
| 77 | + | <location filename="../offlate/window.py" line="361"/> | |
| 53 | 78 | <source>Server:</source> | |
| 54 | 79 | <translation>Serveur :</translation> | |
| 55 | 80 | </message> | |
| 56 | 81 | <message> | |
| 57 | - | <location filename="../offlate/window.py" line="285"/> | |
| 82 | + | <location filename="../offlate/window.py" line="362"/> | |
| 58 | 83 | <source>User Name:</source> | |
| 59 | 84 | <translation>Nom d'utilisateur :</translation> | |
| 60 | 85 | </message> | |
| 86 | + | <message> | |
| 87 | + | <location filename="../offlate/window.py" line="310"/> | |
| 88 | + | <source>Transifex</source> | |
| 89 | + | <translation type="unfinished"></translation> | |
| 90 | + | </message> | |
| 91 | + | <message> | |
| 92 | + | <location filename="../offlate/window.py" line="322"/> | |
| 93 | + | <source>You can get a token from <a href="#">https://www.transifex.com/user/settings/api/</a></source> | |
| 94 | + | <translation type="unfinished"></translation> | |
| 95 | + | </message> | |
| 96 | + | <message> | |
| 97 | + | <location filename="../offlate/window.py" line="325"/> | |
| 98 | + | <source>Token:</source> | |
| 99 | + | <translation type="unfinished"></translation> | |
| 100 | + | </message> | |
| 101 | + | <message> | |
| 102 | + | <location filename="../offlate/window.py" line="339"/> | |
| 103 | + | <source>Translation Project</source> | |
| 104 | + | <translation type="unfinished"></translation> | |
| 105 | + | </message> | |
| 61 | 106 | </context> | |
| 62 | 107 | <context> | |
| 63 | 108 | <name>Window</name> | |
| 64 | 109 | <message> | |
| 65 | - | <location filename="../offlate/window.py" line="356"/> | |
| 110 | + | <location filename="../offlate/window.py" line="433"/> | |
| 66 | 111 | <source>Exit application</source> | |
| 67 | 112 | <translation>Quitter l'application</translation> | |
| 68 | 113 | </message> | |
| 69 | 114 | <message> | |
| 70 | - | <location filename="../offlate/window.py" line="361"/> | |
| 115 | + | <location filename="../offlate/window.py" line="438"/> | |
| 71 | 116 | <source>Save current project</source> | |
| 72 | 117 | <translation>Sauvegarder le projet actuel</translation> | |
| 73 | 118 | </message> | |
| 74 | 119 | <message> | |
| 75 | - | <location filename="../offlate/window.py" line="366"/> | |
| 120 | + | <location filename="../offlate/window.py" line="443"/> | |
| 76 | 121 | <source>New project</source> | |
| 77 | 122 | <translation>Nouveau projet</translation> | |
| 78 | 123 | </message> | |
| 79 | 124 | <message> | |
| 80 | - | <location filename="../offlate/window.py" line="371"/> | |
| 125 | + | <location filename="../offlate/window.py" line="448"/> | |
| 81 | 126 | <source>Get modifications from upstream</source> | |
| 82 | 127 | <translation>R??cup??rer les modifications en amont</translation> | |
| 83 | 128 | </message> | |
| 84 | 129 | <message> | |
| 85 | - | <location filename="../offlate/window.py" line="375"/> | |
| 130 | + | <location filename="../offlate/window.py" line="452"/> | |
| 86 | 131 | <source>Close current project</source> | |
| 87 | 132 | <translation>Fermer le projet actuel</translation> | |
| 88 | 133 | </message> | |
| 89 | 134 | <message> | |
| 90 | - | <location filename="../offlate/window.py" line="380"/> | |
| 135 | + | <location filename="../offlate/window.py" line="457"/> | |
| 91 | 136 | <source>Send modifications upstream</source> | |
| 92 | 137 | <translation>Envoyer les modifications en amont</translation> | |
| 93 | 138 | </message> | |
| 94 | 139 | <message> | |
| 95 | - | <location filename="../offlate/window.py" line="385"/> | |
| 140 | + | <location filename="../offlate/window.py" line="462"/> | |
| 96 | 141 | <source>Set parameters</source> | |
| 97 | 142 | <translation>Configurer les param??tres</translation> | |
| 98 | 143 | </message> | |
| 99 | 144 | <message> | |
| 100 | - | <location filename="../offlate/window.py" line="388"/> | |
| 145 | + | <location filename="../offlate/window.py" line="465"/> | |
| 101 | 146 | <source>Show Translated</source> | |
| 102 | 147 | <translation>Montrer traduites</translation> | |
| 103 | 148 | </message> | |
| 104 | 149 | <message> | |
| 105 | - | <location filename="../offlate/window.py" line="391"/> | |
| 150 | + | <location filename="../offlate/window.py" line="468"/> | |
| 106 | 151 | <source>Show Fuzzy</source> | |
| 107 | 152 | <translation>Montrer floues</translation> | |
| 108 | 153 | </message> | |
| 109 | 154 | <message> | |
| 110 | - | <location filename="../offlate/window.py" line="394"/> | |
| 155 | + | <location filename="../offlate/window.py" line="471"/> | |
| 111 | 156 | <source>Show Empty Translation</source> | |
| 112 | 157 | <translation>Montrer les traductions vides</translation> | |
| 113 | 158 | </message> | |
| 114 | 159 | <message> | |
| 115 | - | <location filename="../offlate/window.py" line="404"/> | |
| 160 | + | <location filename="../offlate/window.py" line="481"/> | |
| 116 | 161 | <source>&File</source> | |
| 117 | 162 | <translation>&Fichier</translation> | |
| 118 | 163 | </message> | |
| 119 | 164 | <message> | |
| 120 | - | <location filename="../offlate/window.py" line="410"/> | |
| 165 | + | <location filename="../offlate/window.py" line="487"/> | |
| 121 | 166 | <source>&Project</source> | |
| 122 | 167 | <translation>&Projet</translation> | |
| 123 | 168 | </message> | |
| 124 | 169 | <message> | |
| 125 | - | <location filename="../offlate/window.py" line="417"/> | |
| 170 | + | <location filename="../offlate/window.py" line="494"/> | |
| 126 | 171 | <source>&Edit</source> | |
| 127 | 172 | <translation>&??dition</translation> | |
| 128 | 173 | </message> | |
| 129 | 174 | <message> | |
| 130 | - | <location filename="../offlate/window.py" line="420"/> | |
| 175 | + | <location filename="../offlate/window.py" line="497"/> | |
| 131 | 176 | <source>&View</source> | |
| 132 | 177 | <translation>&Affichage</translation> | |
| 133 | 178 | </message> | |
| 134 | 179 | <message> | |
| 135 | - | <location filename="../offlate/window.py" line="400"/> | |
| 180 | + | <location filename="../offlate/window.py" line="477"/> | |
| 136 | 181 | <source>Open</source> | |
| 137 | 182 | <translation>Ouvrir</translation> | |
| 138 | 183 | </message> | |
| 139 | 184 | <message> | |
| 140 | - | <location filename="../offlate/window.py" line="354"/> | |
| 185 | + | <location filename="../offlate/window.py" line="431"/> | |
| 141 | 186 | <source>Exit</source> | |
| 142 | 187 | <translation>Quitter</translation> | |
| 143 | 188 | </message> | |
| 144 | 189 | <message> | |
| 145 | - | <location filename="../offlate/window.py" line="359"/> | |
| 190 | + | <location filename="../offlate/window.py" line="436"/> | |
| 146 | 191 | <source>Save</source> | |
| 147 | 192 | <translation>Sauvegarder</translation> | |
| 148 | 193 | </message> | |
| 149 | 194 | <message> | |
| 150 | - | <location filename="../offlate/window.py" line="364"/> | |
| 195 | + | <location filename="../offlate/window.py" line="441"/> | |
| 151 | 196 | <source>New</source> | |
| 152 | 197 | <translation>Nouveau</translation> | |
| 153 | 198 | </message> | |
| 154 | 199 | <message> | |
| 155 | - | <location filename="../offlate/window.py" line="369"/> | |
| 200 | + | <location filename="../offlate/window.py" line="446"/> | |
| 156 | 201 | <source>Update</source> | |
| 157 | 202 | <translation>Mettre ?? jour</translation> | |
| 158 | 203 | </message> | |
| 159 | 204 | <message> | |
| 160 | - | <location filename="../offlate/window.py" line="374"/> | |
| 205 | + | <location filename="../offlate/window.py" line="451"/> | |
| 161 | 206 | <source>Close</source> | |
| 162 | 207 | <translation>Fermer</translation> | |
| 163 | 208 | </message> | |
| 164 | 209 | <message> | |
| 165 | - | <location filename="../offlate/window.py" line="378"/> | |
| 210 | + | <location filename="../offlate/window.py" line="455"/> | |
| 166 | 211 | <source>Send</source> | |
| 167 | 212 | <translation>Envoyer</translation> | |
| 168 | 213 | </message> | |
| 169 | 214 | <message> | |
| 170 | - | <location filename="../offlate/window.py" line="383"/> | |
| 215 | + | <location filename="../offlate/window.py" line="460"/> | |
| 171 | 216 | <source>Settings</source> | |
| 172 | 217 | <translation>Param??tres</translation> | |
| 173 | 218 | </message> | |
| 174 | 219 | </context> | |
| 220 | + | <context> | |
| 221 | + | <name>self.qd</name> | |
| 222 | + | <message> | |
| 223 | + | <location filename="../offlate/window.py" line="24"/> | |
| 224 | + | <source>Please enter your password:</source> | |
| 225 | + | <translation type="unfinished"></translation> | |
| 226 | + | </message> | |
| 227 | + | </context> | |
| 175 | 228 | </TS> | |
offlate/data.json
| 1 | - | [{"name": "a2ps", "system": 0}, {"name": "aegis", "system": 0}, {"name": "anubis", "system": 0}, {"name": "aspell", "system": 0}, {"name": "bash", "system": 0}, {"name": "bfd", "system": 0}, {"name": "binutils", "system": 0}, {"name": "bison", "system": 0}, {"name": "bison-runtime", "system": 0}, {"name": "buzztrax", "system": 0}, {"name": "ccd2cue", "system": 0}, {"name": "ccide", "system": 0}, {"name": "cflow", "system": 0}, {"name": "clisp", "system": 0}, {"name": "coreutils", "system": 0}, {"name": "cpio", "system": 0}, {"name": "cppi", "system": 0}, {"name": "cpplib", "system": 0}, {"name": "cryptsetup", "system": 0}, {"name": "datamash", "system": 0}, {"name": "denemo", "system": 0}, {"name": "dfarc", "system": 0}, {"name": "dialog", "system": 0}, {"name": "dico", "system": 0}, {"name": "diffutils", "system": 0}, {"name": "dink", "system": 0}, {"name": "direvent", "system": 0}, {"name": "doodle", "system": 0}, {"name": "dos2unix", "system": 0}, {"name": "dos2unix-man", "system": 0}, {"name": "e2fsprogs", "system": 0}, {"name": "enscript", "system": 0}, {"name": "exif", "system": 0}, {"name": "fetchmail", "system": 0}, {"name": "findutils", "system": 0}, {"name": "flex", "system": 0}, {"name": "freedink", "system": 0}, {"name": "fusionforge", "system": 0}, {"name": "gas", "system": 0}, {"name": "gawk", "system": 0}, {"name": "gcal", "system": 0}, {"name": "gcc", "system": 0}, {"name": "gdbm", "system": 0}, {"name": "gettext-examples", "system": 0}, {"name": "gettext-runtime", "system": 0}, {"name": "gettext-tools", "system": 0}, {"name": "gjay", "system": 0}, {"name": "glunarclock", "system": 0}, {"name": "gnubiff", "system": 0}, {"name": "gnubik", "system": 0}, {"name": "gnucash", "system": 0}, {"name": "gnuchess", "system": 0}, {"name": "gnucobol", "system": 0}, {"name": "gnulib", "system": 0}, {"name": "gnunet", "system": 0}, {"name": "gnunet-gtk", "system": 0}, {"name": "gold", "system": 0}, {"name": "gphoto2", "system": 0}, {"name": "gprof", "system": 0}, {"name": "gramadoir", "system": 0}, {"name": "grep", "system": 0}, {"name": "grip", "system": 0}, {"name": "grub", "system": 0}, {"name": "gsasl", "system": 0}, {"name": "gss", "system": 0}, {"name": "gst-plugins-bad", "system": 0}, {"name": "gst-plugins-base", "system": 0}, {"name": "gst-plugins-good", "system": 0}, {"name": "gst-plugins-ugly", "system": 0}, {"name": "gstreamer", "system": 0}, {"name": "gtick", "system": 0}, {"name": "gtkam", "system": 0}, {"name": "gtkspell", "system": 0}, {"name": "guix", "system": 0}, {"name": "guix-packages", "system": 0}, {"name": "gutenprint", "system": 0}, {"name": "hello", "system": 0}, {"name": "help2man", "system": 0}, {"name": "help2man-texi", "system": 0}, {"name": "hylafax", "system": 0}, {"name": "idutils", "system": 0}, {"name": "jwhois", "system": 0}, {"name": "kbd", "system": 0}, {"name": "klavaro", "system": 0}, {"name": "ld", "system": 0}, {"name": "leafpad", "system": 0}, {"name": "libc", "system": 0}, {"name": "libexif", "system": 0}, {"name": "libextractor", "system": 0}, {"name": "libgnutls", "system": 0}, {"name": "libgphoto2", "system": 0}, {"name": "libgphoto2_port", "system": 0}, {"name": "libgsasl", "system": 0}, {"name": "libiconv", "system": 0}, {"name": "libidn", "system": 0}, {"name": "libidn2", "system": 0}, {"name": "lilypond", "system": 0}, {"name": "lordsawar", "system": 0}, {"name": "lprng", "system": 0}, {"name": "lynx", "system": 0}, {"name": "m4", "system": 0}, {"name": "mailfromd", "system": 0}, {"name": "mailutils", "system": 0}, {"name": "make", "system": 0}, {"name": "man-db", "system": 0}, {"name": "man-db-manpages", "system": 0}, {"name": "midi-instruments", "system": 0}, {"name": "minicom", "system": 0}, {"name": "mkisofs", "system": 0}, {"name": "muibase", "system": 0}, {"name": "myserver", "system": 0}, {"name": "nano", "system": 0}, {"name": "opcodes", "system": 0}, {"name": "parted", "system": 0}, {"name": "pies", "system": 0}, {"name": "pnmixer", "system": 0}, {"name": "popt", "system": 0}, {"name": "procps-ng", "system": 0}, {"name": "procps-ng-man", "system": 0}, {"name": "psmisc", "system": 0}, {"name": "pspp", "system": 0}, {"name": "pushover", "system": 0}, {"name": "pwdutils", "system": 0}, {"name": "pyspread", "system": 0}, {"name": "radius", "system": 0}, {"name": "recode", "system": 0}, {"name": "recutils", "system": 0}, {"name": "rpm", "system": 0}, {"name": "rush", "system": 0}, {"name": "sarg", "system": 0}, {"name": "savane", "system": 0}, {"name": "sed", "system": 0}, {"name": "sharutils", "system": 0}, {"name": "shepherd", "system": 0}, {"name": "shishi", "system": 0}, {"name": "skribilo", "system": 0}, {"name": "solfege", "system": 0}, {"name": "solfege-manual", "system": 0}, {"name": "spotmachine", "system": 0}, {"name": "sudo", "system": 0}, {"name": "sudoers", "system": 0}, {"name": "sysstat", "system": 0}, {"name": "tar", "system": 0}, {"name": "texinfo", "system": 0}, {"name": "texinfo_document", "system": 0}, {"name": "tigervnc", "system": 0}, {"name": "tin", "system": 0}, {"name": "tin-man", "system": 0}, {"name": "tracgoogleappsauthplugin", "system": 0}, {"name": "trader", "system": 0}, {"name": "util-linux", "system": 0}, {"name": "ve", "system": 0}, {"name": "vmm", "system": 0}, {"name": "vorbis-tools", "system": 0}, {"name": "wastesedge", "system": 0}, {"name": "wcd", "system": 0}, {"name": "wcd-man", "system": 0}, {"name": "wdiff", "system": 0}, {"name": "wget", "system": 0}, {"name": "wyslij-po", "system": 0}, {"name": "xboard", "system": 0}, {"name": "xdg-user-dirs", "system": 0}, {"name": "xkeyboard-config", "system": 0}] | |
| 1 | > | ||
| 2 | 0 | > | \ No newline at end of file |
| 1 | + | [{"name": "a2ps", "system": 0}, {"name": "aegis", "system": 0}, {"name": "anubis", "system": 0}, {"name": "aspell", "system": 0}, {"name": "bash", "system": 0}, {"name": "bfd", "system": 0}, {"name": "binutils", "system": 0}, {"name": "bison", "system": 0}, {"name": "bison-runtime", "system": 0}, {"name": "buzztrax", "system": 0}, {"name": "ccd2cue", "system": 0}, {"name": "ccide", "system": 0}, {"name": "cflow", "system": 0}, {"name": "clisp", "system": 0}, {"name": "coreutils", "system": 0}, {"name": "cpio", "system": 0}, {"name": "cppi", "system": 0}, {"name": "cpplib", "system": 0}, {"name": "cryptsetup", "system": 0}, {"name": "datamash", "system": 0}, {"name": "denemo", "system": 0}, {"name": "dfarc", "system": 0}, {"name": "dialog", "system": 0}, {"name": "dico", "system": 0}, {"name": "diffutils", "system": 0}, {"name": "dink", "system": 0}, {"name": "direvent", "system": 0}, {"name": "doodle", "system": 0}, {"name": "dos2unix", "system": 0}, {"name": "dos2unix-man", "system": 0}, {"name": "e2fsprogs", "system": 0}, {"name": "enscript", "system": 0}, {"name": "exif", "system": 0}, {"name": "fetchmail", "system": 0}, {"name": "findutils", "system": 0}, {"name": "flex", "system": 0}, {"name": "freedink", "system": 0}, {"name": "fusionforge", "system": 0}, {"name": "gas", "system": 0}, {"name": "gawk", "system": 0}, {"name": "gcal", "system": 0}, {"name": "gcc", "system": 0}, {"name": "gdbm", "system": 0}, {"name": "gettext-examples", "system": 0}, {"name": "gettext-runtime", "system": 0}, {"name": "gettext-tools", "system": 0}, {"name": "gjay", "system": 0}, {"name": "glunarclock", "system": 0}, {"name": "gnubiff", "system": 0}, {"name": "gnubik", "system": 0}, {"name": "gnucash", "system": 0}, {"name": "gnuchess", "system": 0}, {"name": "gnucobol", "system": 0}, {"name": "gnulib", "system": 0}, {"name": "gnunet", "system": 0}, {"name": "gnunet-gtk", "system": 0}, {"name": "gold", "system": 0}, {"name": "gphoto2", "system": 0}, {"name": "gprof", "system": 0}, {"name": "gramadoir", "system": 0}, {"name": "grep", "system": 0}, {"name": "grip", "system": 0}, {"name": "grub", "system": 0}, {"name": "gsasl", "system": 0}, {"name": "gss", "system": 0}, {"name": "gst-plugins-bad", "system": 0}, {"name": "gst-plugins-base", "system": 0}, {"name": "gst-plugins-good", "system": 0}, {"name": "gst-plugins-ugly", "system": 0}, {"name": "gstreamer", "system": 0}, {"name": "gtick", "system": 0}, {"name": "gtkam", "system": 0}, {"name": "gtkspell", "system": 0}, {"name": "guix", "system": 0}, {"name": "guix-packages", "system": 0}, {"name": "gutenprint", "system": 0}, {"name": "hello", "system": 0}, {"name": "help2man", "system": 0}, {"name": "help2man-texi", "system": 0}, {"name": "hylafax", "system": 0}, {"name": "idutils", "system": 0}, {"name": "jwhois", "system": 0}, {"name": "kbd", "system": 0}, {"name": "klavaro", "system": 0}, {"name": "ld", "system": 0}, {"name": "leafpad", "system": 0}, {"name": "libc", "system": 0}, {"name": "libexif", "system": 0}, {"name": "libextractor", "system": 0}, {"name": "libgnutls", "system": 0}, {"name": "libgphoto2", "system": 0}, {"name": "libgphoto2_port", "system": 0}, {"name": "libgsasl", "system": 0}, {"name": "libiconv", "system": 0}, {"name": "libidn", "system": 0}, {"name": "libidn2", "system": 0}, {"name": "lilypond", "system": 0}, {"name": "lordsawar", "system": 0}, {"name": "lprng", "system": 0}, {"name": "lynx", "system": 0}, {"name": "m4", "system": 0}, {"name": "mailfromd", "system": 0}, {"name": "mailutils", "system": 0}, {"name": "make", "system": 0}, {"name": "man-db", "system": 0}, {"name": "man-db-manpages", "system": 0}, {"name": "midi-instruments", "system": 0}, {"name": "minicom", "system": 0}, {"name": "mkisofs", "system": 0}, {"name": "muibase", "system": 0}, {"name": "myserver", "system": 0}, {"name": "nano", "system": 0}, {"name": "opcodes", "system": 0}, {"name": "parted", "system": 0}, {"name": "pies", "system": 0}, {"name": "pnmixer", "system": 0}, {"name": "popt", "system": 0}, {"name": "procps-ng", "system": 0}, {"name": "procps-ng-man", "system": 0}, {"name": "psmisc", "system": 0}, {"name": "pspp", "system": 0}, {"name": "pushover", "system": 0}, {"name": "pwdutils", "system": 0}, {"name": "pyspread", "system": 0}, {"name": "radius", "system": 0}, {"name": "recode", "system": 0}, {"name": "recutils", "system": 0}, {"name": "rpm", "system": 0}, {"name": "rush", "system": 0}, {"name": "sarg", "system": 0}, {"name": "savane", "system": 0}, {"name": "sed", "system": 0}, {"name": "sharutils", "system": 0}, {"name": "shepherd", "system": 0}, {"name": "shishi", "system": 0}, {"name": "skribilo", "system": 0}, {"name": "solfege", "system": 0}, {"name": "solfege-manual", "system": 0}, {"name": "spotmachine", "system": 0}, {"name": "sudo", "system": 0}, {"name": "sudoers", "system": 0}, {"name": "sysstat", "system": 0}, {"name": "tar", "system": 0}, {"name": "texinfo", "system": 0}, {"name": "texinfo_document", "system": 0}, {"name": "tigervnc", "system": 0}, {"name": "tin", "system": 0}, {"name": "tin-man", "system": 0}, {"name": "tracgoogleappsauthplugin", "system": 0}, {"name": "trader", "system": 0}, {"name": "util-linux", "system": 0}, {"name": "ve", "system": 0}, {"name": "vmm", "system": 0}, {"name": "vorbis-tools", "system": 0}, {"name": "wastesedge", "system": 0}, {"name": "wcd", "system": 0}, {"name": "wcd-man", "system": 0}, {"name": "wdiff", "system": 0}, {"name": "wget", "system": 0}, {"name": "wyslij-po", "system": 0}, {"name": "xboard", "system": 0}, {"name": "xdg-user-dirs", "system": 0}, {"name": "xkeyboard-config", "system": 0}, {"name": "id-editor", "system": 1, "organisation": "openstreetmap"}] |
offlate/manager.py
| 1 | 1 | from pathlib import Path | |
| 2 | 2 | from .systems.tp import TPProject | |
| 3 | + | from .systems.transifex import TransifexProject | |
| 3 | 4 | ||
| 4 | 5 | import json | |
| 5 | 6 | import os | |
… | |||
| 39 | 40 | if not "TP" in self.settings.conf: | |
| 40 | 41 | self.settings.conf["TP"] = {} | |
| 41 | 42 | self.project_list[p['name']] = \ | |
| 42 | - | TPProject(self.settings.conf["TP"], p['name'], p['lang']) | |
| 43 | - | self.project_list[p['name']].open(self.basedir+'/'+p['name'], p['info']['version']) | |
| 44 | - | except Exception: | |
| 43 | + | TPProject(self.settings.conf["TP"], p['name'], p['lang'], p['info']) | |
| 44 | + | self.project_list[p['name']].open(self.basedir+'/'+p['name']) | |
| 45 | + | if p['system'] == 1: | |
| 46 | + | if not "Transifex" in self.settings.conf: | |
| 47 | + | self.settings.conf['Transifex'] = {} | |
| 48 | + | self.project_list[p['name']] = \ | |
| 49 | + | TransifexProject(self.settings.conf['Transifex'], p['name'], p['lang'], p['info']) | |
| 50 | + | self.project_list[p['name']].open(self.basedir+'/'+p['name']) | |
| 51 | + | except Exception as e: | |
| 52 | + | print(e) | |
| 45 | 53 | with open(self.basedir + '/projects.json', 'w') as f: | |
| 46 | 54 | f.write(json.dumps([])) | |
| 47 | 55 | ||
| 48 | - | def createProject(self, name, lang, system): | |
| 56 | + | def createProject(self, name, lang, system, data): | |
| 49 | 57 | projectpath = self.basedir + '/' + name | |
| 50 | 58 | Path(projectpath).mkdir(parents=True) | |
| 51 | 59 | if system == 0: #TP | |
… | |||
| 56 | 64 | self.project_list[name] = proj | |
| 57 | 65 | self.projects.append({"name": name, "lang": lang, "system": system, | |
| 58 | 66 | "info": {"version": proj.version}}) | |
| 67 | + | if system == 1: #Transifex | |
| 68 | + | if not 'Transifex' in self.settings.conf: | |
| 69 | + | self.settings.conf['Transifex'] = {} | |
| 70 | + | proj = TransifexProject(self.settings.conf['Transifex'], name, lang, data) | |
| 71 | + | proj.initialize(projectpath) | |
| 72 | + | self.project_list[name] = proj | |
| 73 | + | self.projects.append({"name": name, "lang": lang, "system": system, | |
| 74 | + | "info": data}) | |
| 59 | 75 | self.writeProjects() | |
| 60 | 76 | ||
| 61 | 77 | def writeProjects(self): | |
offlate/systems/entry.py unknown status 1
| 1 | + | class Entry: | |
| 2 | + | def __init__(self, msgids, msgstrs, fuzzy, obsolete): | |
| 3 | + | self.msgids = msgids | |
| 4 | + | self.msgstrs = msgstrs | |
| 5 | + | self.fuzzy = fuzzy | |
| 6 | + | self.obsolete = obsolete | |
| 7 | + | ||
| 8 | + | def isTranslated(self): | |
| 9 | + | for msgstr in self.msgstrs: | |
| 10 | + | if msgstr == '': | |
| 11 | + | return False | |
| 12 | + | return True | |
| 13 | + | ||
| 14 | + | def isFuzzy(self): | |
| 15 | + | return self.fuzzy | |
| 16 | + | ||
| 17 | + | def isObsolete(self): | |
| 18 | + | return self.obsolete | |
| 19 | + | ||
| 20 | + | def update(self, index, content): | |
| 21 | + | self.msgstrs[index] = content | |
| 22 | + | ||
| 23 | + | class POEntry(Entry): | |
| 24 | + | def __init__(self, entry): | |
| 25 | + | msgids = [entry.msgid] | |
| 26 | + | msgstrs = [entry.msgstr] | |
| 27 | + | if 0 in entry.msgstr_plural: | |
| 28 | + | msgstrs = [] | |
| 29 | + | for msgstr in entry.msgstr_plural: | |
| 30 | + | msgstrs.append(entry.msgstr_plural[msgstr]) | |
| 31 | + | msgids = [entry.msgid, entry.msgid_plural] | |
| 32 | + | Entry.__init__(self, msgids, msgstrs, "fuzzy" in entry.flags, entry.obsolete) | |
| 33 | + | self.entry = entry | |
| 34 | + | ||
| 35 | + | def update(self, index, content): | |
| 36 | + | Entry.update(self, index, content) | |
| 37 | + | if 0 in self.entry.msgstr_plural: | |
| 38 | + | self.entry.msgstr_plural[index] = content | |
| 39 | + | else: | |
| 40 | + | self.entry.msgstr = content | |
| 41 | + | ||
| 42 | + | class JSONEntry(Entry): | |
| 43 | + | def __init__(self, entry): | |
| 44 | + | Entry.__init__(self, [entry['source_string']], [entry['translation']], False, False) | |
| 45 | + | self.entry = entry | |
| 46 | + | ||
| 47 | + | def update(self, index, content): | |
| 48 | + | Entry.update(self, index, content) | |
| 49 | + | self.entry['translation'] = content | |
| 50 | + | ||
| 51 | + | class YAMLEntry(Entry): | |
| 52 | + | def __init__(self, entry): | |
| 53 | + | self.key = list(entry.keys())[0] | |
| 54 | + | Entry.__init__(self, self.key, entry[self.key], False, False) | |
| 55 | + | self.entry = entry | |
| 56 | + | ||
| 57 | + | def update(self, index, content): | |
| 58 | + | Entry.update(self, index, content) | |
| 59 | + | self.entry[self.key] = content |
offlate/systems/tp.py
| 11 | 11 | import os | |
| 12 | 12 | from pathlib import Path | |
| 13 | 13 | ||
| 14 | + | from .entry import POEntry | |
| 15 | + | ||
| 14 | 16 | class TPProject: | |
| 15 | - | def __init__(self, conf, name, lang): | |
| 17 | + | def __init__(self, conf, name, lang, data = {}): | |
| 16 | 18 | self.uri = "https://translationproject.org" | |
| 17 | 19 | self.conf = conf | |
| 18 | 20 | self.name = name | |
| 19 | 21 | self.lang = lang | |
| 20 | 22 | self.basedir = '' | |
| 23 | + | self.info = data | |
| 24 | + | if "version" in data: | |
| 25 | + | self.version = data['version'] | |
| 21 | 26 | ||
| 22 | - | def open(self, basedir, version): | |
| 23 | - | self.version = version | |
| 27 | + | def open(self, basedir): | |
| 24 | 28 | self.basedir = basedir | |
| 25 | 29 | self.updateFileName() | |
| 26 | 30 | self.updateGettextNames() | |
… | |||
| 104 | 108 | newpo.save() | |
| 105 | 109 | ||
| 106 | 110 | def send(self, interface): | |
| 111 | + | self.save() | |
| 107 | 112 | msg = EmailMessage() | |
| 108 | 113 | msg['Subject'] = self.filename | |
| 109 | 114 | msg['From'] = self.conf["email"] | |
… | |||
| 116 | 121 | s.login(self.conf['user'], interface.askPassword()) | |
| 117 | 122 | s.send_message(msg) | |
| 118 | 123 | ||
| 124 | + | def save(self): | |
| 125 | + | self.po.save() | |
| 126 | + | ||
| 119 | 127 | def content(self): | |
| 120 | - | po = polib.pofile(self.popath) | |
| 121 | - | return po | |
| 128 | + | self.po = polib.pofile(self.popath) | |
| 129 | + | po = [POEntry(x) for x in self.po] | |
| 130 | + | return {'default': po} | |
offlate/systems/transifex.py unknown status 1
| 1 | + | import requests | |
| 2 | + | import json | |
| 3 | + | from ruamel import yaml | |
| 4 | + | import os | |
| 5 | + | ||
| 6 | + | from requests.auth import HTTPBasicAuth | |
| 7 | + | ||
| 8 | + | from pathlib import Path | |
| 9 | + | ||
| 10 | + | from .entry import JSONEntry | |
| 11 | + | ||
| 12 | + | def yaml_rec_load(path, source, dest): | |
| 13 | + | ans = [] | |
| 14 | + | for s in source: | |
| 15 | + | path2 = list(path) | |
| 16 | + | path2.append(s) | |
| 17 | + | if isinstance(source[s], str): | |
| 18 | + | ans.append({'path': path, 'id': s, 'source_string': source[s], 'translation': dest[s]}) | |
| 19 | + | else: | |
| 20 | + | ans.extend(yaml_rec_load(path2, source[s], dest[s])) | |
| 21 | + | return ans | |
| 22 | + | ||
| 23 | + | class TransifexProject: | |
| 24 | + | def __init__(self, conf, name, lang, data = {}): | |
| 25 | + | self.uri = "https://www.transifex.com" | |
| 26 | + | self.conf = conf | |
| 27 | + | self.name = name | |
| 28 | + | self.lang = lang | |
| 29 | + | self.data = data | |
| 30 | + | self.basedir = '' | |
| 31 | + | self.contents = {} | |
| 32 | + | ||
| 33 | + | def open(self, basedir): | |
| 34 | + | self.basedir = basedir | |
| 35 | + | with open(self.basedir + '/project.info') as f: | |
| 36 | + | self.files = json.load(f) | |
| 37 | + | self.slugs = [x['slug'] for x in self.files] | |
| 38 | + | self.loadContent() | |
| 39 | + | ||
| 40 | + | def initialize(self, basedir): | |
| 41 | + | self.basedir = basedir | |
| 42 | + | self.updateFileList() | |
| 43 | + | with open(self.basedir + '/project.info', 'w') as f: | |
| 44 | + | f.write(json.dumps(self.files)) | |
| 45 | + | for slug in self.slugs: | |
| 46 | + | self.getFile(slug) | |
| 47 | + | self.loadContent() | |
| 48 | + | ||
| 49 | + | def update(self, callback): | |
| 50 | + | self.updateFileList() | |
| 51 | + | ||
| 52 | + | def updateFileList(self): | |
| 53 | + | self.files = [] | |
| 54 | + | self.slugs = [] | |
| 55 | + | ans = requests.get('https://api.transifex.com/organizations/'+ | |
| 56 | + | self.data['organization']+'/projects/'+self.name+ | |
| 57 | + | '/resources/?language_code='+self.lang, | |
| 58 | + | auth=HTTPBasicAuth('api', self.conf['token'])) | |
| 59 | + | if ans.status_code == 200: | |
| 60 | + | l = json.loads(ans.text) | |
| 61 | + | self.slugs = [x['slug'] for x in l] | |
| 62 | + | self.files = l | |
| 63 | + | ||
| 64 | + | def loadContent(self): | |
| 65 | + | for ff in self.files: | |
| 66 | + | with open(self.filename(ff['slug'], True)) as f: | |
| 67 | + | with open(self.filename(ff['slug'], False)) as f2: | |
| 68 | + | if ff['i18n_type'] == 'YML': | |
| 69 | + | source = yaml.safe_load(f) | |
| 70 | + | dest = yaml.safe_load(f2) | |
| 71 | + | lang1 = list(source.keys())[0] | |
| 72 | + | lang2 = list(dest.keys())[0] | |
| 73 | + | self.contents[ff['slug']] = \ | |
| 74 | + | yaml_rec_load([lang2], source[lang1], dest[lang2]) | |
| 75 | + | ||
| 76 | + | def getFile(self, slug): | |
| 77 | + | ans = requests.get('https://www.transifex.com/api/2/project/'+ | |
| 78 | + | self.name+'/resource/'+slug+'/content', | |
| 79 | + | auth=HTTPBasicAuth('api', self.conf['token'])) | |
| 80 | + | if ans.status_code == 200: | |
| 81 | + | with open(self.filename(slug, True), 'w') as f: | |
| 82 | + | f.write(json.loads(ans.text)['content']) | |
| 83 | + | ||
| 84 | + | ans = requests.get('https://www.transifex.com/api/2/project/'+self.name+ | |
| 85 | + | '/resource/'+slug+'/translation/'+self.lang+'/?mode=translator', | |
| 86 | + | auth=HTTPBasicAuth('api', self.conf['token'])) | |
| 87 | + | if ans.status_code == 200: | |
| 88 | + | with open(self.filename(slug, False), 'w') as f: | |
| 89 | + | f.write(json.loads(ans.text)['content']) | |
| 90 | + | else: | |
| 91 | + | print(ans.text) | |
| 92 | + | ||
| 93 | + | def filename(self, slug, is_source): | |
| 94 | + | ext = '' | |
| 95 | + | for ff in self.files: | |
| 96 | + | if ff['slug'] == slug: | |
| 97 | + | f = ff | |
| 98 | + | break | |
| 99 | + | if f['i18n_type'] == 'YML': | |
| 100 | + | ext = 'yml' | |
| 101 | + | return self.basedir + '/' + slug + ('.source' if is_source else '') + '.' + ext | |
| 102 | + | ||
| 103 | + | def send(self, interface): | |
| 104 | + | self.save() | |
| 105 | + | for ff in self.files: | |
| 106 | + | print('{} => {}'.format(ff['slug'], ff['i18n_type'])) | |
| 107 | + | with open(self.filename(ff['slug'], False)) as f: | |
| 108 | + | content = f.read() | |
| 109 | + | sendcontent = {"content": content} | |
| 110 | + | ans = requests.put('https://www.transifex.com/api/2/project/'+ | |
| 111 | + | self.name+'/resource/'+ff['slug']+'/translation/'+self.lang+'/', | |
| 112 | + | json=sendcontent, auth=HTTPBasicAuth('api', self.conf['token'])) | |
| 113 | + | print(ans) | |
| 114 | + | print(ans.text) | |
| 115 | + | #for slug in self.slugs: | |
| 116 | + | # with open(self.filename(slug)) as f: | |
| 117 | + | # content = json.load(f) | |
| 118 | + | # sendcontent = {} | |
| 119 | + | # for s in content: | |
| 120 | + | # sendcontent[s['source_string']] = s['translation'] | |
| 121 | + | # sendcontent = {'content': json.dumps({'content': sendcontent})} | |
| 122 | + | # ans = requests.put('https://www.transifex.com/api/2/project/'+ | |
| 123 | + | # self.name+'/resource/'+slug+'/translation/'+self.lang+'/', | |
| 124 | + | # json=sendcontent, auth=HTTPBasicAuth('api', self.conf['token'])) | |
| 125 | + | # print(ans) | |
| 126 | + | # print(ans.text) | |
| 127 | + | ||
| 128 | + | def save(self): | |
| 129 | + | for slug in self.slugs: | |
| 130 | + | data = {} | |
| 131 | + | for d in self.contents[slug]: | |
| 132 | + | path = d['path'] | |
| 133 | + | curr = data | |
| 134 | + | for p in path: | |
| 135 | + | if p in curr: | |
| 136 | + | curr = curr[p] | |
| 137 | + | else: | |
| 138 | + | curr[p] = {} | |
| 139 | + | curr = curr[p] | |
| 140 | + | curr[d['id']] = d['translation'] | |
| 141 | + | with open(self.filename(slug, False), 'w') as f: | |
| 142 | + | yaml.dump(data, f, Dumper=yaml.RoundTripDumper, allow_unicode=True) | |
| 143 | + | ||
| 144 | + | def content(self): | |
| 145 | + | contents = {} | |
| 146 | + | for content in self.contents: | |
| 147 | + | contents[content] = [JSONEntry(x) for x in self.contents[content]] | |
| 148 | + | return contents |
offlate/window.py
| 21 | 21 | ||
| 22 | 22 | def askPassword(self): | |
| 23 | 23 | self.qd = QInputDialog() | |
| 24 | + | self.qd.setLabelText(self.qd.tr("Please enter your password:")) | |
| 24 | 25 | self.qd.setTextEchoMode(QLineEdit.Password) | |
| 25 | 26 | self.qd.accepted.connect(self.ok) | |
| 26 | 27 | self.qd.exec_() | |
… | |||
| 31 | 32 | super(ProjectView, self).__init__(parent) | |
| 32 | 33 | self.project = project | |
| 33 | 34 | self.content = self.project.content() | |
| 35 | + | self.currentContent = list(self.content.keys())[0] | |
| 34 | 36 | self.showTranslated = showTranslated | |
| 35 | 37 | self.showUntranslated = showUntranslated | |
| 36 | 38 | self.showFuzzy = showFuzzy | |
… | |||
| 39 | 41 | def updateContent(self): | |
| 40 | 42 | self.treeWidget.clear() | |
| 41 | 43 | items = [] | |
| 42 | - | for entry in self.content: | |
| 43 | - | if entry.obsolete: | |
| 44 | + | for entry in self.content[self.currentContent]: | |
| 45 | + | if entry.isObsolete(): | |
| 44 | 46 | continue | |
| 45 | 47 | cont = False | |
| 46 | - | if self.showTranslated and entry.translated(): | |
| 48 | + | if self.showTranslated and entry.isTranslated(): | |
| 47 | 49 | cont = True | |
| 48 | - | if self.showUntranslated and not entry.translated(): | |
| 50 | + | if self.showUntranslated and not entry.isTranslated(): | |
| 49 | 51 | cont = True | |
| 50 | - | if self.showFuzzy and 'fuzzy' in entry.flags: | |
| 52 | + | if self.showFuzzy and entry.isFuzzy(): | |
| 51 | 53 | cont = True | |
| 52 | 54 | if not cont: | |
| 53 | 55 | continue | |
| 54 | - | msgstr = entry.msgstr | |
| 55 | - | if 0 in entry.msgstr_plural: | |
| 56 | - | msgstr = entry.msgstr_plural[0] | |
| 57 | - | item = QTreeWidgetItem([entry.msgid, msgstr]) | |
| 56 | + | item = QTreeWidgetItem([entry.msgids[0], entry.msgstrs[0]]) | |
| 58 | 57 | item.setData(0, Qt.UserRole, entry) | |
| 59 | 58 | items.append(item) | |
| 60 | 59 | self.treeWidget.insertTopLevelItems(0, items) | |
… | |||
| 68 | 67 | self.msgid = QTextEdit() | |
| 69 | 68 | self.msgid.setReadOnly(True) | |
| 70 | 69 | self.msgstr = QTextEdit() | |
| 70 | + | self.filechooser = QComboBox() | |
| 71 | + | for project in list(self.content.keys()): | |
| 72 | + | self.filechooser.addItem(project) | |
| 73 | + | self.filechooser.currentIndexChanged.connect(self.changefile) | |
| 74 | + | ||
| 75 | + | if self.filechooser.count() > 1: | |
| 76 | + | vbox.addWidget(self.filechooser) | |
| 71 | 77 | ||
| 72 | 78 | self.updateContent() | |
| 73 | 79 | vbox.addWidget(self.treeWidget, 4) | |
… | |||
| 79 | 85 | self.treeWidget.setColumnWidth(0, size.width()/2) | |
| 80 | 86 | self.treeWidget.currentItemChanged.connect(self.selectItem) | |
| 81 | 87 | ||
| 88 | + | def changefile(self): | |
| 89 | + | self.currentContent = list(self.content.keys())[self.filechooser.currentIndex()] | |
| 90 | + | self.updateContent() | |
| 91 | + | ||
| 82 | 92 | def selectItem(self, current, old): | |
| 83 | 93 | if current == None: | |
| 84 | 94 | return | |
… | |||
| 87 | 97 | self.hbox.removeWidget(self.msgstr) | |
| 88 | 98 | self.msgid.deleteLater() | |
| 89 | 99 | self.msgstr.deleteLater() | |
| 90 | - | if 0 in data.msgstr_plural: | |
| 100 | + | ||
| 101 | + | if len(data.msgstrs) > 1: | |
| 91 | 102 | self.msgid = QTabWidget(); | |
| 92 | 103 | self.msgstr = QTabWidget(); | |
| 93 | 104 | singular = QTextEdit() | |
| 94 | 105 | singular.setReadOnly(True) | |
| 95 | - | singular.setText(data.msgid) | |
| 106 | + | singular.setText(data.msgids[0]) | |
| 96 | 107 | plural = QTextEdit() | |
| 97 | 108 | plural.setReadOnly(True) | |
| 98 | - | plural.setText(data.msgid_plural) | |
| 109 | + | plural.setText(data.msgids[1]) | |
| 99 | 110 | self.msgid.addTab(singular, self.tr("Singular")) | |
| 100 | 111 | self.msgid.addTab(plural, self.tr("Plural")) | |
| 101 | 112 | i = 0 | |
| 102 | - | while i in data.msgstr_plural: | |
| 113 | + | for msgstr in data.msgstrs: | |
| 103 | 114 | form = QTextEdit() | |
| 104 | - | form.setText(data.msgstr_plural[i]) | |
| 115 | + | form.setText(msgstr) | |
| 105 | 116 | form.textChanged.connect(self.modify) | |
| 106 | 117 | self.msgstr.addTab(form, str(i)) | |
| 107 | 118 | i=i+1 | |
… | |||
| 109 | 120 | self.msgid = QTextEdit() | |
| 110 | 121 | self.msgid.setReadOnly(True) | |
| 111 | 122 | self.msgstr = QTextEdit() | |
| 112 | - | self.msgid.setText(data.msgid) | |
| 113 | - | self.msgstr.setText(data.msgstr) | |
| 123 | + | self.msgid.setText(data.msgids[0]) | |
| 124 | + | self.msgstr.setText(data.msgstrs[0]) | |
| 114 | 125 | self.msgstr.textChanged.connect(self.modify) | |
| 115 | 126 | self.hbox.addWidget(self.msgid) | |
| 116 | 127 | self.hbox.addWidget(self.msgstr) | |
… | |||
| 119 | 130 | item = self.treeWidget.currentItem() | |
| 120 | 131 | data = item.data(0, Qt.UserRole) | |
| 121 | 132 | if self.msgstr.__class__.__name__ == "QTextEdit": | |
| 122 | - | data.msgstr = self.msgstr.toPlainText() | |
| 123 | - | item.setText(1, data.msgstr) | |
| 133 | + | msgstr = self.msgstr.toPlainText() | |
| 134 | + | data.update(0, msgstr) | |
| 135 | + | item.setText(1, msgstr) | |
| 124 | 136 | else: | |
| 125 | 137 | i = 0 | |
| 126 | - | while i in data.msgstr_plural: | |
| 127 | - | data.msgstr_plural[i] = self.msgstr.widget(i).toPlainText() | |
| 138 | + | for msgstr in data.msgstrs: | |
| 139 | + | data.update(i, self.msgstr.widget(i).toPlainText()) | |
| 128 | 140 | i=i+1 | |
| 129 | 141 | item.setText(1, data.msgstr_plural[0]) | |
| 130 | 142 | ||
| 131 | 143 | def save(self): | |
| 132 | - | self.content.save() | |
| 144 | + | self.project.save() | |
| 133 | 145 | ||
| 134 | 146 | def send(self): | |
| 135 | - | self.content.save() | |
| 147 | + | self.project.save() | |
| 136 | 148 | self.project.send(Interface()) | |
| 137 | 149 | ||
| 138 | 150 | def askmerge(self, msgid, oldstr, newstr): | |
… | |||
| 140 | 152 | return newstr | |
| 141 | 153 | ||
| 142 | 154 | def update(self): | |
| 143 | - | self.content.save() | |
| 155 | + | self.project.save() | |
| 144 | 156 | self.project.update(self.askmerge) | |
| 145 | 157 | self.content = self.project.content() | |
| 146 | 158 | self.updateContent() | |
… | |||
| 176 | 188 | predefinedbox.addWidget(self.predefinedprojects) | |
| 177 | 189 | ||
| 178 | 190 | contentbox = QVBoxLayout() | |
| 191 | + | formbox = QGroupBox(self.tr("Project information")) | |
| 192 | + | self.formLayout = QFormLayout() | |
| 193 | + | formbox.setLayout(self.formLayout) | |
| 194 | + | ||
| 179 | 195 | self.nameWidget = QLineEdit() | |
| 180 | 196 | self.langWidget = QLineEdit() | |
| 181 | - | contentbox.addWidget(self.nameWidget) | |
| 182 | - | contentbox.addWidget(self.langWidget) | |
| 197 | + | self.formLayout.addRow(QLabel(self.tr("Name:")), self.nameWidget) | |
| 198 | + | self.formLayout.addRow(QLabel(self.tr("Target Language:")), self.langWidget) | |
| 183 | 199 | self.combo = QComboBox() | |
| 184 | 200 | self.combo.addItem(self.tr("The Translation Project")) | |
| 185 | - | contentbox.addWidget(self.combo) | |
| 201 | + | self.combo.addItem(self.tr("Transifex")) | |
| 202 | + | self.formLayout.addRow(self.combo) | |
| 203 | + | ||
| 186 | 204 | hhbox = QHBoxLayout() | |
| 187 | 205 | cancel = QPushButton(self.tr("Cancel")) | |
| 188 | 206 | ok = QPushButton(self.tr("OK")) | |
| 189 | 207 | hhbox.addWidget(cancel) | |
| 190 | 208 | hhbox.addWidget(ok) | |
| 209 | + | contentbox.addWidget(formbox) | |
| 191 | 210 | contentbox.addLayout(hhbox) | |
| 192 | 211 | hbox.addLayout(predefinedbox) | |
| 193 | 212 | hbox.addLayout(contentbox) | |
| 194 | 213 | ||
| 214 | + | self.additionalFields = [] | |
| 215 | + | self.additionalFields.append([]) | |
| 216 | + | self.additionalFields.append([]) | |
| 217 | + | self.transifexOrganisation = QLineEdit() | |
| 218 | + | transifexOrganisationLabel = QLabel(self.tr("Organization")) | |
| 219 | + | self.additionalFields[1].append({'label': transifexOrganisationLabel, | |
| 220 | + | 'widget': self.transifexOrganisation}) | |
| 221 | + | ||
| 195 | 222 | self.setLayout(hbox) | |
| 196 | 223 | ||
| 197 | 224 | self.predefinedprojects.currentItemChanged.connect(self.fill) | |
| 198 | 225 | cancel.clicked.connect(self.close) | |
| 199 | 226 | ok.clicked.connect(self.ok) | |
| 200 | 227 | self.searchfield.textChanged.connect(self.filter) | |
| 228 | + | self.combo.currentIndexChanged.connect(self.othersystem) | |
| 201 | 229 | ||
| 202 | 230 | def ok(self): | |
| 203 | 231 | self.askNew = True | |
… | |||
| 208 | 236 | data = item.data(Qt.UserRole) | |
| 209 | 237 | self.nameWidget.setText(data['name']) | |
| 210 | 238 | self.combo.setCurrentIndex(int(data['system'])) | |
| 239 | + | if data['system'] == 1: | |
| 240 | + | self.transifexOrganisation.setText(data['organisation']) | |
| 211 | 241 | ||
| 212 | 242 | def filter(self): | |
| 213 | 243 | search = self.searchfield.text() | |
… | |||
| 231 | 261 | def getProjectSystem(self): | |
| 232 | 262 | return self.combo.currentIndex() | |
| 233 | 263 | ||
| 264 | + | def getProjectInfo(self): | |
| 265 | + | if self.getProjectSystem() == 0: | |
| 266 | + | return {} | |
| 267 | + | if self.getProjectSystem() == 1: | |
| 268 | + | return {'organization': self.additionalFields[1][0]['widget'].text()} | |
| 269 | + | return {} | |
| 270 | + | ||
| 271 | + | def othersystem(self): | |
| 272 | + | for system in self.additionalFields: | |
| 273 | + | for widget in system: | |
| 274 | + | self.formLayout.takeRow(widget['widget']) | |
| 275 | + | widget['widget'].hide() | |
| 276 | + | widget['label'].hide() | |
| 277 | + | self.formLayout.invalidate() | |
| 278 | + | for widget in self.additionalFields[self.combo.currentIndex()]: | |
| 279 | + | self.formLayout.addRow(widget['label'], widget['widget']) | |
| 280 | + | widget['widget'].show() | |
| 281 | + | widget['label'].show() | |
| 282 | + | ||
| 234 | 283 | class SettingsWindow(QDialog): | |
| 235 | 284 | def __init__(self, preferences, parent = None): | |
| 236 | 285 | super().__init__(parent) | |
… | |||
| 352 | 401 | if not w.wantNew(): | |
| 353 | 402 | return | |
| 354 | 403 | self.manager.createProject(w.getProjectName(), w.getProjectLang(), | |
| 355 | - | w.getProjectSystem()) | |
| 404 | + | w.getProjectSystem(), w.getProjectInfo()) | |
| 356 | 405 | self.open(w.getProjectName()) | |
| 357 | 406 | ||
| 358 | 407 | def send(self): | |
setup.py
| 5 | 5 | version="0.1.dev", | |
| 6 | 6 | packages=find_packages(exclude=['.guix-profile*']), | |
| 7 | 7 | python_requires = '>=3', | |
| 8 | - | install_requires=['polib'], | |
| 8 | + | install_requires=['polib', 'PyYAML'], | |
| 9 | 9 | entry_points={ | |
| 10 | 10 | 'gui_scripts': [ | |
| 11 | 11 | 'offlate=offlate.window:main', |