From 134d2ea974454fa859103c4a302ffa4960ef1871 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 29 Apr 2021 20:38:14 +0000 Subject: [PATCH] Localize and translate into French the add-on * Localize all the strings so that the whole add-on can be translated (menus, notifications, etc.) * Translate all the strings into French * Add advice for future translators in the contribution guidelines * List the supported languages in the README and a link to the translation guidelines * Rearrange the parts of the README to have the most used information at the top --- README.md | 36 ++++--- contributing.md | 16 ++- .../resource.language.en_gb/strings.po | 97 +++++++++++++++++- .../resource.language.fr_fr/strings.po | 99 ++++++++++++++++++- resources/lib/addon.py | 60 ++++++----- resources/lib/kodi_utils.py | 31 +++--- resources/lib/peertube.py | 19 ++-- service.py | 4 +- 8 files changed, 288 insertions(+), 74 deletions(-) diff --git a/README.md b/README.md index 399de3c..c55b10c 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,16 @@ If you want to contribute, please start with the [contribution guidelines](contributing.md) and the [pending issues](https://framagit.org/StCyr/plugin.video.peertube/-/issues). +--- + [[_TOC_]] +# Installation and prerequisites + +Please read the +[wiki](https://framagit.org/StCyr/plugin.video.peertube/-/wikis/home) +for more information. + # Features * Play videos (including live videos) @@ -21,6 +29,19 @@ If you want to contribute, please start with the If not available, it will play the higher resolution that is the closest from your preference. +The following languages are available: English and French. +If you want to help translating the add-on in your language, check +[here](contributing.md#translation). + +# Limitations + +* This add-on doesn't support Webtorrent yet. So, it cannot download/share + from/to regular PeerTube clients. +* The add-on doesn't delete the downloaded files at the moment so it may fill + up your disk. You may delete manually the downloaded files in the folder + `/temp/plugin.video.peertube/` (more information about + `` [here](https://kodi.wiki/view/Kodi_data_folder#Location)). + # User settings * Preferred PeerTube instance @@ -57,18 +78,3 @@ For instance to play the video behind the URL the add-on with: `plugin://plugin.video.peertube/?action=play_video&instance=framatube.org&id=9c9de5e8-0a1e-484a-b099-e80766180a6d` - -# Limitations - -* This add-on doesn't support Webtorrent yet. So, it cannot download/share - from/to regular PeerTube clients. -* The add-on doesn't delete the downloaded files at the moment so it may fill - up your disk. You may delete manually the downloaded files in the folder - `/temp/plugin.video.peertube/` (more information on `` - [here](https://kodi.wiki/view/Kodi_data_folder#Location)). - -# Installation and prerequisites - -Please read the -[wiki](https://framagit.org/StCyr/plugin.video.peertube/-/wikis/home) -for more information. diff --git a/contributing.md b/contributing.md index 4a4e8f1..79c990f 100644 --- a/contributing.md +++ b/contributing.md @@ -149,10 +149,20 @@ To translate the add-on you may: `resources/language` * create a new `strings.po` for your language +More information about the translation system used by Kodi and its add-ons is +available [here](https://kodi.wiki/view/Language_support). + +While translating please take care to: +* Keep the `{}`: they will be replaced by variables in the code +* Keep the punctuation but adapt it to your language's rules (for instance the + number of spaces around `:` varies from one language to another) +* Translate using the meaning of the original string but try to not exceed too + much the length of the original string (otherwise it may have a negative + impact on the user experience e.g. with overlapping strings) +* If you hesitate between several translations for a "technical" word, try to + use the translation of this word from the Kodi interface + A CI job called `translation` is available in each merge request which contains changes in strings.po files. It checks that the reference strings in the translation files are the same as in the reference file ([resources/language/resource.language.en_gb/strings.po](./resources/language/resource.language.en_gb/strings.po)). - -More information on the translation system used by Kodi and its add-ons is -available [here](https://kodi.wiki/view/Language_support). diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po index 7a8500a..ff6d4eb 100644 --- a/resources/language/resource.language.en_gb/strings.po +++ b/resources/language/resource.language.en_gb/strings.po @@ -14,10 +14,15 @@ msgstr "" "Language: en_GB\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -# Settings (from 30000 to 30019) +# Only IDs from 30000 to 30999 can be used by plugins. +# (from https://kodi.wiki/view/Language_support#String_ID_range) + +# ----------------------------------- +# Settings (from 30000 to 30399) +# ----------------------------------- msgctxt "#30000" -msgid "Preferred instance" +msgid "Instance URL" msgstr "" msgctxt "#30001" @@ -71,3 +76,91 @@ msgstr "" msgctxt "#30013" msgid "Display a notification when the service starts" msgstr "" + +# ----------------------------------- +# Other strings (from 30400 to 30999) +# ----------------------------------- + +msgctxt "#30400" +msgid "PeerTube service started" +msgstr "" + +msgctxt "#30401" +msgid "Torrents can now be downloaded." +msgstr "" + +msgctxt "#30402" +msgid "Request error" +msgstr "" + +msgctxt "#30403" +msgid "No details returned by the server. Check the log for more information." +msgstr "" + +msgctxt "#30404" +msgid "{}\n\n----------\nNumber of local videos: {}\nNumber of users: {}" +msgstr "" + +msgctxt "#30405" +msgid "Next page" +msgstr "" + +msgctxt "#30406" +msgid "Browse videos on the selected instance" +msgstr "" + +msgctxt "#30407" +msgid "Search videos on the selected instance" +msgstr "" + +msgctxt "#30408" +msgid "Select another instance" +msgstr "" + +msgctxt "#30409" +msgid "Search videos on {}" +msgstr "" + +msgctxt "#30410" +msgid "No videos found" +msgstr "" + +msgctxt "#30411" +msgid "No videos found matching the keywords '{}'" +msgstr "" + +msgctxt "#30412" +msgid "Error: libtorrent could not be imported" +msgstr "" + +msgctxt "#30413" +msgid "PeerTube cannot play videos without libtorrent\nPlease follow the instructions at {}" +msgstr "" + +msgctxt "#30414" +msgid "Download started" +msgstr "" + +msgctxt "#30415" +msgid "The video will be played soon." +msgstr "" + +msgctxt "#30416" +msgid "Download timeout" +msgstr "" + +msgctxt "#30417" +msgid "Timeout while downloading {}" +msgstr "" + +msgctxt "#30418" +msgid "Instance changed" +msgstr "" + +msgctxt "#30419" +msgid "{} is now the selected instance" +msgstr "" + +msgctxt "#30420" +msgid "You can still browse and search videos but you will not be able to play them (except live videos).\nPlease follow the instructions at {}" +msgstr "" diff --git a/resources/language/resource.language.fr_fr/strings.po b/resources/language/resource.language.fr_fr/strings.po index 05ada12..c13a0b1 100644 --- a/resources/language/resource.language.fr_fr/strings.po +++ b/resources/language/resource.language.fr_fr/strings.po @@ -14,11 +14,16 @@ msgstr "" "Language: fr_FR\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -# Settings (from 30000 to 30019) +# Only IDs from 30000 to 30999 can be used by plugins. +# (from https://kodi.wiki/view/Language_support#String_ID_range) + +# ----------------------------------- +# Settings (from 30000 to 30399) +# ----------------------------------- msgctxt "#30000" -msgid "Preferred instance" -msgstr "Instance préférée" +msgid "Instance URL" +msgstr "URL de l'instance" msgctxt "#30001" msgid "Number of items to show per page" @@ -71,3 +76,91 @@ msgstr "nombre de vues" msgctxt "#30013" msgid "Display a notification when the service starts" msgstr "Afficher une notification au démarrage du service" + +# ----------------------------------- +# Other strings (from 30400 to 30999) +# ----------------------------------- + +msgctxt "#30400" +msgid "PeerTube service started" +msgstr "Le service PeerTube a démarré" + +msgctxt "#30401" +msgid "Torrents can now be downloaded." +msgstr "Les torrents peuvent maintenant être téléchargés." + +msgctxt "#30402" +msgid "Request error" +msgstr "Erreur de la requête" + +msgctxt "#30403" +msgid "No details returned by the server. Check the log for more information." +msgstr "Le serveur n'a pas renvoyé de détails. Voir le journal pour plus d'informations." + +msgctxt "#30404" +msgid "{}\n\n----------\nNumber of local videos: {}\nNumber of users: {}" +msgstr "{}\n\n----------\nNombre de vidéos locales: {}\nNombre d'utilisateurs: {}" + +msgctxt "#30405" +msgid "Next page" +msgstr "Page suivante" + +msgctxt "#30406" +msgid "Browse videos on the selected instance" +msgstr "Parcourir les vidéos sur l'instance sélectionnée" + +msgctxt "#30407" +msgid "Search videos on the selected instance" +msgstr "Rechercher des vidéos sur l'instance sélectionnée" + +msgctxt "#30408" +msgid "Select another instance" +msgstr "Sélectionner une autre instance" + +msgctxt "#30409" +msgid "Search videos on {}" +msgstr "Rechercher des vidéos sur {}" + +msgctxt "#30410" +msgid "No videos found" +msgstr "Aucune vidéo trouvée" + +msgctxt "#30411" +msgid "No videos found matching the keywords '{}'" +msgstr "Aucune vidéo ne correspond aux mots-clés '{}'" + +msgctxt "#30412" +msgid "Error: libtorrent could not be imported" +msgstr "Erreur: libtorrent n'a pas pu être importé" + +msgctxt "#30413" +msgid "PeerTube cannot play videos without libtorrent\nPlease follow the instructions at {}" +msgstr "PeerTube ne peut pas lire de vidéos sans libtorrent.\nMerci de suivre les instructions depuis {}" + +msgctxt "#30414" +msgid "Download started" +msgstr "Démarrage du téléchargement" + +msgctxt "#30415" +msgid "The video will be played soon." +msgstr "La video va être bientôt lue." + +msgctxt "#30416" +msgid "Download timeout" +msgstr "Délai d'attente dépassé" + +msgctxt "#30417" +msgid "Timeout while downloading {}" +msgstr "Délai d'attente dépassé lors du téléchargement de {}" + +msgctxt "#30418" +msgid "Instance changed" +msgstr "Instance modifiée" + +msgctxt "#30419" +msgid "{} is now the selected instance" +msgstr "{} est maintenant l'instance sélectionnée" + +msgctxt "#30420" +msgid "You can still browse and search videos but you will not be able to play them (except live videos).\nPlease follow the instructions at {}" +msgstr "Vous pouvez parcourir ou chercher des vidéos mais vous ne pourrez pas les lire (sauf les live).\nMerci de suivre les instructions depuis {}" diff --git a/resources/lib/addon.py b/resources/lib/addon.py index 82eabaa..0ff5a13 100644 --- a/resources/lib/addon.py +++ b/resources/lib/addon.py @@ -97,13 +97,11 @@ class PeerTubeAddon(): # * the description of the instance (from joinpeertube.org) # * the number of local videos hosted on this instance # * the number of users on this instance - description = "{}\n\n----------\nNumber of local videos: {}\n"\ - "Number of users: {}".format( - data["shortDescription"].encode("utf-8"), - data["totalLocalVideos"], - data["totalUsers"]) - # The value of "totalLocalVideos" and "totalUsers" are int so they - # don't need to be encoded. + description = kodi.get_string(30404).format( + data["shortDescription"], + data["totalLocalVideos"], + data["totalUsers"] + ) instance_info = kodi.generate_item_info( name=data["name"], @@ -201,7 +199,9 @@ class PeerTubeAddon(): total_pages = (total / self.items_per_page) + 1 next_page_item = kodi.generate_item_info( - name="Next page ({}/{})".format(next_page, total_pages), + name="{} ({}/{})".format(kodi.get_string(30405), + next_page, + total_pages), url=url ) @@ -281,15 +281,15 @@ class PeerTubeAddon(): home_page_items = [ kodi.generate_item_info( - name="Browse videos on the selected instance", + name=kodi.get_string(30406), url=kodi.build_kodi_url({"action": "browse_videos","start": 0}) ), kodi.generate_item_info( - name="Search videos on the selected instance", + name=kodi.get_string(30407), url=kodi.build_kodi_url({"action": "search_videos","start": 0}) ), kodi.generate_item_info( - name="Select another instance", + name=kodi.get_string(30408), url=kodi.build_kodi_url({ "action": "browse_instances", "start": 0 @@ -309,7 +309,7 @@ class PeerTubeAddon(): # Ask the user which keywords must be searched for keywords = kodi.open_input_box( - title="Search videos on {}".format(self.peertube.instance)) + title=kodi.get_string(30409).format(self.peertube.instance)) # Go back to the home page when the user cancels or didn't enter any # string @@ -322,9 +322,8 @@ class PeerTubeAddon(): # Exit directly when no result is found if not results: kodi.notif_warning( - title="No videos found", - message="No videos found matching the keywords '{}'" - .format(keywords)) + title=kodi.get_string(30410), + message=kodi.get_string(30411).format(keywords)) return # Extract the information of each video from the API response @@ -343,15 +342,13 @@ class PeerTubeAddon(): # download nor play the video as it will fail. if not self.libtorrent_imported: kodi.open_dialog( - title="Error: libtorrent could not be imported", - message="PeerTube cannot play videos without libtorrent\n" - "Please follow the instructions at {}" - .format(self.HELP_URL)) + title=kodi.get_string(30412), + message=kodi.get_string(30413).format(self.HELP_URL)) return kodi.debug("Starting torrent download ({})".format(torrent_url)) - kodi.notif_info(title="Download started", - message="The video will be played soon.") + kodi.notif_info(title=kodi.get_string(30414), + message=kodi.get_string(30415)) # Start a downloader thread AddonSignals.sendSignal("start_download", {"url": torrent_url}) @@ -369,8 +366,8 @@ class PeerTubeAddon(): # Abort in case of timeout if timeout == 10: kodi.notif_error( - title="Download timeout", - message="Timeout fetching {}".format(torrent_url)) + title=kodi.get_string(30416), + message=kodi.get_string(30417).format(torrent_url)) return else: # Wait a little before starting playing the torrent @@ -411,10 +408,12 @@ class PeerTubeAddon(): kodi.set_setting("preferred_instance", instance) # Notify the user and log the event - message = \ - "{} is now the selected instance".format(self.peertube.instance) - kodi.notif_info(title="Current instance changed", message=message) - kodi.debug(message) + kodi.notif_info( + title=kodi.get_string(30418), + message=kodi.get_string(30419).format(self.peertube.instance)) + + kodi.debug("{} is now the selected instance" + .format(self.peertube.instance)) def router(self, params): """Route the add-on to the requested actions @@ -460,8 +459,5 @@ class PeerTubeAddon(): # Display a warning if libtorrent could not be imported if not self.libtorrent_imported: kodi.open_dialog( - title="Error: libtorrent could not be imported", - message="You can still browse and search videos but you" - " will not be able to play them (except live" - " videos).\nPlease follow the instructions at {}" - .format(self.HELP_URL)) + title=kodi.get_string(30412), + message=kodi.get_string(30420).format(self.HELP_URL)) diff --git a/resources/lib/kodi_utils.py b/resources/lib/kodi_utils.py index 2f8f091..512bdcb 100644 --- a/resources/lib/kodi_utils.py +++ b/resources/lib/kodi_utils.py @@ -132,6 +132,16 @@ class KodiUtils: } } + def get_property(self, name): + """Retrieve the value of a window property related to the add-on + + :param str name: Name of the property which value will be retrieved (the + actual name of the property is prefixed with "peertube_") + :return: Value of the window property + :rtype: str + """ + return xbmcgui.Window(10000).getProperty("peertube_{}".format(name)) + def get_run_parameters(self): """Return the parameter the add-on was called with @@ -143,16 +153,6 @@ class KodiUtils: # The first character ("?") is skipped return dict(parse_qsl(self.addon_parameters[1:])) - def get_property(self, name): - """Retrieve the value of a window property related to the add-on - - :param str name: Name of the property which value will be retrieved (the - actual name of the property is prefixed with "peertube_") - :return: Value of the window property - :rtype: str - """ - return xbmcgui.Window(10000).getProperty("peertube_{}".format(name)) - def get_setting(self, setting_name): """Retrieve the value of a setting @@ -162,6 +162,15 @@ class KodiUtils: """ return xbmcaddon.Addon().getSetting(setting_name) + def get_string(self, string_id): + """Retrieve a localized string + + :param int string_id: ID of the string in strings.po + :return: the localized value of the string + :rtype: str + """ + return xbmcaddon.Addon().getLocalizedString(string_id) + def notif_error(self, title, message): """Display a notification with the error icon @@ -255,4 +264,4 @@ class KodiUtils: self.addon_handle = int(argv[1]) self.addon_parameters = argv[2] -kodi = KodiUtils() \ No newline at end of file +kodi = KodiUtils() diff --git a/resources/lib/peertube.py b/resources/lib/peertube.py index 5c1a4ef..13b7383 100644 --- a/resources/lib/peertube.py +++ b/resources/lib/peertube.py @@ -81,13 +81,17 @@ class PeerTube: # Report the error to the user with a notification: if the response # contains an "error" attribute, use it as error message, otherwise # use a default message. + # Note: in case the error attribute is used, the message will be in + # English whatever the language configured by the user. It's better + # to share the information with the user (even if it's not in its + # language) rather than always redirecting to the Kodi's log. if "error" in json: message = json["error"] kodi.debug(message) else: - message = ("No details returned by the server. Check the log" - " for more information.") - kodi.notif_error(title="Request error", message=message) + message = kodi.get_string(30403) + + kodi.notif_error(title=kodi.get_string(30402), message=message) raise exception return json @@ -264,6 +268,10 @@ def list_instances(start): # Report the error to the user with a notification: use the details of # the error if it exists in the response, otherwise use a default # message. + # Note: in case the error is reused from the response, the message will + # be in English whatever the language configured by the user. It's + # better to share the information with the user (even if it's not in + # its language) rather than always redirecting to the Kodi's log. try: # Convert the reponse to a list to get the first error whatever its # name. Then get the second element in the sublist which contains @@ -271,9 +279,8 @@ def list_instances(start): message = list(json["errors"].items())[0][1]["msg"] kodi.debug(message) except KeyError: - message = ("No details returned by the server. Check the log" - " for more information.") - kodi.notif_error(title="Request error", message=message) + message = kodi.get_string(30403) + kodi.notif_error(title=kodi.get_string(30402), message=message) raise exception return json diff --git a/service.py b/service.py index 831ce76..b68145a 100644 --- a/service.py +++ b/service.py @@ -129,8 +129,8 @@ class PeertubeService(): # Monitor Kodi's shutdown signal self.debug("Service started, waiting for signals") if kodi.get_setting("service_start_notif") == "true": - kodi.notif_info(title="PeerTube service started", - message="Torrents can now be downloaded.") + kodi.notif_info(title=kodi.get_string(30400), + message=kodi.get_string(30401)) monitor = xbmc.Monitor() while not monitor.abortRequested(): if monitor.waitForAbort(1):