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
This commit is contained in:
Thomas 2021-04-29 20:38:14 +00:00
parent 939f1f0ea5
commit 134d2ea974
8 changed files with 288 additions and 74 deletions

View File

@ -6,8 +6,16 @@ If you want to contribute, please start with the
[contribution guidelines](contributing.md) and the [contribution guidelines](contributing.md) and the
[pending issues](https://framagit.org/StCyr/plugin.video.peertube/-/issues). [pending issues](https://framagit.org/StCyr/plugin.video.peertube/-/issues).
---
[[_TOC_]] [[_TOC_]]
# Installation and prerequisites
Please read the
[wiki](https://framagit.org/StCyr/plugin.video.peertube/-/wikis/home)
for more information.
# Features # Features
* Play videos (including live videos) * 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 If not available, it will play the higher resolution that is the closest from
your preference. 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
`<kodi_home>/temp/plugin.video.peertube/` (more information about
`<kodi_home>` [here](https://kodi.wiki/view/Kodi_data_folder#Location)).
# User settings # User settings
* Preferred PeerTube instance * Preferred PeerTube instance
@ -57,18 +78,3 @@ For instance to play the video behind the URL
the add-on with: the add-on with:
`plugin://plugin.video.peertube/?action=play_video&instance=framatube.org&id=9c9de5e8-0a1e-484a-b099-e80766180a6d` `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
`<kodi_home>/temp/plugin.video.peertube/` (more information on `<kodi_home>`
[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.

View File

@ -149,10 +149,20 @@ To translate the add-on you may:
`resources/language` `resources/language`
* create a new `strings.po` for your 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 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 changes in strings.po files. It checks that the reference strings in the
translation files are the same as in the reference file 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)). ([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).

View File

@ -14,10 +14,15 @@ msgstr ""
"Language: en_GB\n" "Language: en_GB\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\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" msgctxt "#30000"
msgid "Preferred instance" msgid "Instance URL"
msgstr "" msgstr ""
msgctxt "#30001" msgctxt "#30001"
@ -71,3 +76,91 @@ msgstr ""
msgctxt "#30013" msgctxt "#30013"
msgid "Display a notification when the service starts" msgid "Display a notification when the service starts"
msgstr "" 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 ""

View File

@ -14,11 +14,16 @@ msgstr ""
"Language: fr_FR\n" "Language: fr_FR\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\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" msgctxt "#30000"
msgid "Preferred instance" msgid "Instance URL"
msgstr "Instance préférée" msgstr "URL de l'instance"
msgctxt "#30001" msgctxt "#30001"
msgid "Number of items to show per page" msgid "Number of items to show per page"
@ -71,3 +76,91 @@ msgstr "nombre de vues"
msgctxt "#30013" msgctxt "#30013"
msgid "Display a notification when the service starts" msgid "Display a notification when the service starts"
msgstr "Afficher une notification au démarrage du service" 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 {}"

View File

@ -97,13 +97,11 @@ class PeerTubeAddon():
# * the description of the instance (from joinpeertube.org) # * the description of the instance (from joinpeertube.org)
# * the number of local videos hosted on this instance # * the number of local videos hosted on this instance
# * the number of users on this instance # * the number of users on this instance
description = "{}\n\n----------\nNumber of local videos: {}\n"\ description = kodi.get_string(30404).format(
"Number of users: {}".format( data["shortDescription"],
data["shortDescription"].encode("utf-8"), data["totalLocalVideos"],
data["totalLocalVideos"], data["totalUsers"]
data["totalUsers"]) )
# The value of "totalLocalVideos" and "totalUsers" are int so they
# don't need to be encoded.
instance_info = kodi.generate_item_info( instance_info = kodi.generate_item_info(
name=data["name"], name=data["name"],
@ -201,7 +199,9 @@ class PeerTubeAddon():
total_pages = (total / self.items_per_page) + 1 total_pages = (total / self.items_per_page) + 1
next_page_item = kodi.generate_item_info( 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 url=url
) )
@ -281,15 +281,15 @@ class PeerTubeAddon():
home_page_items = [ home_page_items = [
kodi.generate_item_info( 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}) url=kodi.build_kodi_url({"action": "browse_videos","start": 0})
), ),
kodi.generate_item_info( 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}) url=kodi.build_kodi_url({"action": "search_videos","start": 0})
), ),
kodi.generate_item_info( kodi.generate_item_info(
name="Select another instance", name=kodi.get_string(30408),
url=kodi.build_kodi_url({ url=kodi.build_kodi_url({
"action": "browse_instances", "action": "browse_instances",
"start": 0 "start": 0
@ -309,7 +309,7 @@ class PeerTubeAddon():
# Ask the user which keywords must be searched for # Ask the user which keywords must be searched for
keywords = kodi.open_input_box( 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 # Go back to the home page when the user cancels or didn't enter any
# string # string
@ -322,9 +322,8 @@ class PeerTubeAddon():
# Exit directly when no result is found # Exit directly when no result is found
if not results: if not results:
kodi.notif_warning( kodi.notif_warning(
title="No videos found", title=kodi.get_string(30410),
message="No videos found matching the keywords '{}'" message=kodi.get_string(30411).format(keywords))
.format(keywords))
return return
# Extract the information of each video from the API response # 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. # download nor play the video as it will fail.
if not self.libtorrent_imported: if not self.libtorrent_imported:
kodi.open_dialog( kodi.open_dialog(
title="Error: libtorrent could not be imported", title=kodi.get_string(30412),
message="PeerTube cannot play videos without libtorrent\n" message=kodi.get_string(30413).format(self.HELP_URL))
"Please follow the instructions at {}"
.format(self.HELP_URL))
return return
kodi.debug("Starting torrent download ({})".format(torrent_url)) kodi.debug("Starting torrent download ({})".format(torrent_url))
kodi.notif_info(title="Download started", kodi.notif_info(title=kodi.get_string(30414),
message="The video will be played soon.") message=kodi.get_string(30415))
# Start a downloader thread # Start a downloader thread
AddonSignals.sendSignal("start_download", {"url": torrent_url}) AddonSignals.sendSignal("start_download", {"url": torrent_url})
@ -369,8 +366,8 @@ class PeerTubeAddon():
# Abort in case of timeout # Abort in case of timeout
if timeout == 10: if timeout == 10:
kodi.notif_error( kodi.notif_error(
title="Download timeout", title=kodi.get_string(30416),
message="Timeout fetching {}".format(torrent_url)) message=kodi.get_string(30417).format(torrent_url))
return return
else: else:
# Wait a little before starting playing the torrent # Wait a little before starting playing the torrent
@ -411,10 +408,12 @@ class PeerTubeAddon():
kodi.set_setting("preferred_instance", instance) kodi.set_setting("preferred_instance", instance)
# Notify the user and log the event # Notify the user and log the event
message = \ kodi.notif_info(
"{} is now the selected instance".format(self.peertube.instance) title=kodi.get_string(30418),
kodi.notif_info(title="Current instance changed", message=message) message=kodi.get_string(30419).format(self.peertube.instance))
kodi.debug(message)
kodi.debug("{} is now the selected instance"
.format(self.peertube.instance))
def router(self, params): def router(self, params):
"""Route the add-on to the requested actions """Route the add-on to the requested actions
@ -460,8 +459,5 @@ class PeerTubeAddon():
# Display a warning if libtorrent could not be imported # Display a warning if libtorrent could not be imported
if not self.libtorrent_imported: if not self.libtorrent_imported:
kodi.open_dialog( kodi.open_dialog(
title="Error: libtorrent could not be imported", title=kodi.get_string(30412),
message="You can still browse and search videos but you" message=kodi.get_string(30420).format(self.HELP_URL))
" will not be able to play them (except live"
" videos).\nPlease follow the instructions at {}"
.format(self.HELP_URL))

View File

@ -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): def get_run_parameters(self):
"""Return the parameter the add-on was called with """Return the parameter the add-on was called with
@ -143,16 +153,6 @@ class KodiUtils:
# The first character ("?") is skipped # The first character ("?") is skipped
return dict(parse_qsl(self.addon_parameters[1:])) 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): def get_setting(self, setting_name):
"""Retrieve the value of a setting """Retrieve the value of a setting
@ -162,6 +162,15 @@ class KodiUtils:
""" """
return xbmcaddon.Addon().getSetting(setting_name) 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): def notif_error(self, title, message):
"""Display a notification with the error icon """Display a notification with the error icon
@ -255,4 +264,4 @@ class KodiUtils:
self.addon_handle = int(argv[1]) self.addon_handle = int(argv[1])
self.addon_parameters = argv[2] self.addon_parameters = argv[2]
kodi = KodiUtils() kodi = KodiUtils()

View File

@ -81,13 +81,17 @@ class PeerTube:
# Report the error to the user with a notification: if the response # Report the error to the user with a notification: if the response
# contains an "error" attribute, use it as error message, otherwise # contains an "error" attribute, use it as error message, otherwise
# use a default message. # 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: if "error" in json:
message = json["error"] message = json["error"]
kodi.debug(message) kodi.debug(message)
else: else:
message = ("No details returned by the server. Check the log" message = kodi.get_string(30403)
" for more information.")
kodi.notif_error(title="Request error", message=message) kodi.notif_error(title=kodi.get_string(30402), message=message)
raise exception raise exception
return json return json
@ -264,6 +268,10 @@ def list_instances(start):
# Report the error to the user with a notification: use the details of # 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 # the error if it exists in the response, otherwise use a default
# message. # 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: try:
# Convert the reponse to a list to get the first error whatever its # Convert the reponse to a list to get the first error whatever its
# name. Then get the second element in the sublist which contains # 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"] message = list(json["errors"].items())[0][1]["msg"]
kodi.debug(message) kodi.debug(message)
except KeyError: except KeyError:
message = ("No details returned by the server. Check the log" message = kodi.get_string(30403)
" for more information.") kodi.notif_error(title=kodi.get_string(30402), message=message)
kodi.notif_error(title="Request error", message=message)
raise exception raise exception
return json return json

View File

@ -129,8 +129,8 @@ class PeertubeService():
# Monitor Kodi's shutdown signal # Monitor Kodi's shutdown signal
self.debug("Service started, waiting for signals") self.debug("Service started, waiting for signals")
if kodi.get_setting("service_start_notif") == "true": if kodi.get_setting("service_start_notif") == "true":
kodi.notif_info(title="PeerTube service started", kodi.notif_info(title=kodi.get_string(30400),
message="Torrents can now be downloaded.") message=kodi.get_string(30401))
monitor = xbmc.Monitor() monitor = xbmc.Monitor()
while not monitor.abortRequested(): while not monitor.abortRequested():
if monitor.waitForAbort(1): if monitor.waitForAbort(1):