Skip to content

Commit

Permalink
Integrate pyformat with localize()
Browse files Browse the repository at this point in the history
By integrating string formattig with the localize() function call we can
make both the translations easier to comprehend, as well as the code
more transparant/readable.

And by using SafeDict() it is also more reliable if arguments do not add up.
When a key is not found the 'template' remains in the string.
  • Loading branch information
dagwieers committed Jul 15, 2019
1 parent 4becfc0 commit 85d6c48
Show file tree
Hide file tree
Showing 11 changed files with 94 additions and 37 deletions.
10 changes: 5 additions & 5 deletions resources/language/resource.language.en_gb/strings.po
Original file line number Diff line number Diff line change
Expand Up @@ -634,11 +634,11 @@ msgid "Please increase the maximum bandwidth. Maximum bandwidth is set to {max}
msgstr ""

msgctxt "#30958"
msgid "There is a problem with this VRT NU %s stream. Try again with %s %s %s or try to play this program from the VRT NU website. Please report this problem at https://www.vrt.be/vrtnu/help/"
msgid "There is a problem with this VRT NU {protocol} stream. Try again with {component} {state} or try to play this program from the VRT NU website. Please report this problem at https://www.vrt.be/vrtnu/help/"
msgstr ""

msgctxt "#30959"
msgid "and Widevine DRM"
msgid "InputStream Adaptive and Widevine DRM"
msgstr ""

msgctxt "#30960"
Expand All @@ -650,7 +650,7 @@ msgid "enabled"
msgstr ""

msgctxt "#30962"
msgid "There is a problem with this VRT NU %s stream and Kodi %s does not support the alternative stream. Please upgrade to a newer Kodi version or try to play this program from the VRT NU website. Please report this problem at https://www.vrt.be/vrtnu/help/"
msgid "There is a problem with this VRT NU {protocol} stream and Kodi {version} does not support the alternative stream. Please upgrade to a newer Kodi version or try to play this program from the VRT NU website. Please report this problem at https://www.vrt.be/vrtnu/help/"
msgstr ""

msgctxt "#30965"
Expand Down Expand Up @@ -678,7 +678,7 @@ msgid "Failed to get favorites token from VRT NU"
msgstr ""

msgctxt "#30976"
msgid "Failed to (un)follow program '%s' at VRT NU"
msgid "Failed to (un)follow program '{program}' at VRT NU"
msgstr ""

msgctxt "#30978"
Expand Down Expand Up @@ -714,7 +714,7 @@ msgid "Successfully cleared VRT tokens."
msgstr ""

msgctxt "#30986"
msgid "No on demand stream available for %s."
msgid "No on demand stream available for {title}."
msgstr ""

msgctxt "#30990"
Expand Down
20 changes: 10 additions & 10 deletions resources/language/resource.language.nl_nl/strings.po
Original file line number Diff line number Diff line change
Expand Up @@ -526,12 +526,12 @@ msgid "Please increase the maximum bandwidth. Maximum bandwidth is set to {max}
msgstr "Verhoog de maximale bandbreedte alstublieft. De maximale bandbreedte is ingesteld op {max} kbps, maar deze stream heeft minimum {min} kbps nodig."

msgctxt "#30958"
msgid "There is a problem with this VRT NU %s stream. Try again with %s %s %s or try to play this program from the VRT NU website. Please report this problem at https://www.vrt.be/vrtnu/help/"
msgstr "Er is een probleem met deze VRT NU %s-stream. Probeer het opnieuw met %s %s %s of probeer dit programma af te spelen vanaf de VRT NU-website. Meld dit probleem op https://www.vrt.be/vrtnu/help/"
msgid "There is a problem with this VRT NU {protocol} stream. Try again with {component} {state} or try to play this program from the VRT NU website. Please report this problem at https://www.vrt.be/vrtnu/help/"
msgstr "Er is een probleem met deze VRT NU {protocol}-stream. Probeer het opnieuw met {component} {state} of probeer dit programma af te spelen vanaf de VRT NU-website. Meld dit probleem op https://www.vrt.be/vrtnu/help/"

msgctxt "#30959"
msgid "and Widevine DRM"
msgstr "en Widevine DRM"
msgid "InputStream Adaptive and Widevine DRM"
msgstr "InputStream Adaptive en Widevine DRM"

msgctxt "#30960"
msgid "disabled"
Expand All @@ -542,8 +542,8 @@ msgid "enabled"
msgstr "ingeschakeld"

msgctxt "#30962"
msgid "There is a problem with this VRT NU %s stream and Kodi %s does not support the alternative stream. Please upgrade to a newer Kodi version or try to play this program from the VRT NU website. Please report this problem at https://www.vrt.be/vrtnu/help/"
msgstr "Er is een probleem met deze VRT NU %s-stream en Kodi %s ondersteunt de alternatieve stream niet. Schakel over op een nieuwere versie van Kodi of probeer dit programma af te spelen vanaf de VRT NU-website. Meld dit probleem op https://www.vrt.be/vrtnu/help/"
msgid "There is a problem with this VRT NU {protocol} stream and Kodi {version} does not support the alternative stream. Please upgrade to a newer Kodi version or try to play this program from the VRT NU website. Please report this problem at https://www.vrt.be/vrtnu/help/"
msgstr "Er is een probleem met deze VRT NU {protocol}-stream en Kodi {version} ondersteunt de alternatieve stream niet. Schakel over op een nieuwere versie van Kodi of probeer dit programma af te spelen vanaf de VRT NU-website. Meld dit probleem op https://www.vrt.be/vrtnu/help/"

msgctxt "#30965"
msgid "Using a SOCKS proxy requires the PySocks library (script.module.pysocks) installed."
Expand All @@ -570,8 +570,8 @@ msgid "Failed to get favorites token from VRT NU"
msgstr "Ophalen van het favorieten token van VRT NU is mislukt"

msgctxt "#30976"
msgid "Failed to (un)follow program '%s' at VRT NU"
msgstr "Het programma '%s' op VRT NU volgen of vergeten is mislukt"
msgid "Failed to (un)follow program '{program}' at VRT NU"
msgstr "Het programma '{program}' op VRT NU volgen of vergeten is mislukt"

msgctxt "#30978"
msgid "Welcome to VRT NU add-on v2.0.0"
Expand Down Expand Up @@ -606,8 +606,8 @@ msgid "Successfully cleared VRT tokens."
msgstr "VRT tokens werden verwijderd."

msgctxt "#30986"
msgid "No on demand stream available for %s."
msgstr "Geen on demand stream beschikbaar voor %s"
msgid "No on demand stream available for {title}."
msgstr "Geen on demand stream beschikbaar voor {title}"

msgctxt "#30990"
msgid "This program cannot be played. To view this program outside of Belgium, you first have to validate a Belgian mobile phone number on the VRT NU website."
Expand Down
8 changes: 8 additions & 0 deletions resources/lib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@

from __future__ import absolute_import, division, unicode_literals

login_gateway_url = 'https://login.vrt.be'
profile_gateway_url = 'https://profiel.vrt.be'
search_gateway_url = 'https://search.vrt.be/search'
search_suggest_gateway_url = 'https://search.vrt.be/suggest'
token_gateway_url = 'https://token.vrt.be'
userdata_gateway_url = 'https://video-user-data.vrt.be'
vualto_url = 'cdn.vuplay.co.uk/vrt/vuplay'

# Fallback list of categories so we don't depend on web scraping only
CATEGORIES = [
dict(name='Audiodescriptie', id='met-audiodescriptie', msgctxt='30070'),
Expand Down
6 changes: 3 additions & 3 deletions resources/lib/favorites.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ def set_favorite(self, program, title, value=True):

xvrttoken = self._tokenresolver.get_xvrttoken(token_variant='user')
if xvrttoken is None:
self._kodi.show_notification(message=self._kodi.localize(30975))
self._kodi.log_error('Failed to get favorites token from VRT NU')
self._kodi.show_notification(message=self._kodi.localize(30975))
return False

headers = {
Expand All @@ -81,8 +81,8 @@ def set_favorite(self, program, title, value=True):
req = Request('https://video-user-data.vrt.be/favorites/%s' % self.uuid(program), data=data, headers=headers)
result = urlopen(req)
if result.getcode() != 200:
self._kodi.show_notification(message=self._kodi.localize(30976) % program)
self._kodi.log_error("Failed to (un)follow program '%s' at VRT NU" % program)
self._kodi.log_error("Failed to (un)follow program '{program}' at VRT NU".format(program=program))
self._kodi.show_notification(message=self._kodi.localize(30976, program=program))
return False
# NOTE: Updates to favorites take a longer time to take effect, so we keep our own cache and use it
self._favorites[self.uuid(program)] = dict(value=payload)
Expand Down
15 changes: 13 additions & 2 deletions resources/lib/kodiwrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ def has_socks():
return has_socks.installed


class SafeDict(dict):
''' A safe dictionary implementation that does not break down on missing keys '''
def __missing__(self, key):
''' Replace missing keys with the original placeholder '''
return '{' + key + '}'


class KodiWrapper:
''' A wrapper around all Kodi functionality '''

Expand Down Expand Up @@ -291,8 +298,12 @@ def set_locale(self):
self.log_notice("Your system does not support locale '%s': %s" % (locale_lang, e), 'Debug')
return False

def localize(self, string_id):
''' Return the translated string from the .po language files '''
def localize(self, string_id, **kwargs):
''' Return the translated string from the .po language files, optionally translating variables '''
if kwargs:
import string
return string.Formatter().vformat(self._addon.getLocalizedString(string_id), (), SafeDict(**kwargs))

return self._addon.getLocalizedString(string_id)

def localize_date(self, date, strftime):
Expand Down
2 changes: 1 addition & 1 deletion resources/lib/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def search(self, keywords=None, page=None):
self.add(keywords)
search_items, sort, ascending, content = self._apihelper.get_search_items(keywords, page=page)
if not search_items:
self._kodi.show_ok_dialog(heading=self._kodi.localize(30098), message=self._kodi.localize(30099).format(keywords=keywords))
self._kodi.show_ok_dialog(heading=self._kodi.localize(30098), message=self._kodi.localize(30099, keywords=keywords))
self._kodi.end_of_directory()
return

Expand Down
12 changes: 6 additions & 6 deletions resources/lib/streamservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,15 +291,15 @@ def _handle_bad_stream_error(self, protocol):
'''
# HLS AES DRM failed
if protocol == 'hls_aes' and not self._kodi.supports_drm():
message = self._kodi.localize(30962) % (protocol.upper(), self._kodi.kodi_version())
message = self._kodi.localize(30962, protocol=protocol.upper(), version=self._kodi.kodi_version())
elif protocol == 'hls_aes' and not self._kodi.has_inputstream_adaptive() and self._kodi.get_setting('usedrm', 'true') == 'false':
message = self._kodi.localize(30958) % (protocol.upper(), 'InputStream Adaptive', self._kodi.localize(30959), self._kodi.localize(30961))
message = self._kodi.localize(30958, protocol=protocol.upper(), component=self._kodi.localize(30959), state=self._kodi.localize(30961))
elif protocol == 'hls_aes' and self._kodi.has_inputstream_adaptive():
message = self._kodi.localize(30958) % (protocol.upper(), 'Widevine DRM', '', self._kodi.localize(30961))
message = self._kodi.localize(30958, protocol=protocol.upper(), component='Widevine DRM', state=self._kodi.localize(30961))
elif protocol == 'hls_aes' and self._kodi.get_setting('usedrm', 'true') == 'true':
message = self._kodi.localize(30958) % (protocol.upper(), 'InputStream Adaptive', '', self._kodi.localize(30961))
message = self._kodi.localize(30958, protocol=protocol.upper(), component='InputStream Adaptive', state=self._kodi.localize(30961))
else:
message = self._kodi.localize(30958) % (protocol.upper(), 'InputStream Adaptive', '', self._kodi.localize(30960))
message = self._kodi.localize(30958, protocol=protocol.upper(), component='InputStream Adaptive', state=self._kodi.localize(30960))
self._kodi.show_ok_dialog(message=message)
self._kodi.end_of_directory()

Expand Down Expand Up @@ -338,7 +338,7 @@ def _select_hls_substreams(self, master_hls_url, protocol):
break

if stream_bandwidth > max_bandwidth and not hls_variant_url:
message = self._kodi.localize(30057).format(max=max_bandwidth, min=stream_bandwidth)
message = self._kodi.localize(30057, max=max_bandwidth, min=stream_bandwidth)
self._kodi.show_ok_dialog(message=message)
self._kodi.open_settings()

Expand Down
2 changes: 1 addition & 1 deletion resources/lib/tvguide.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def show_channel_menu(self, date):

fanart = 'resource://resource.images.studios.coloured/%(studio)s.png' % channel
thumb = 'resource://resource.images.studios.white/%(studio)s.png' % channel
plot = '%s\n%s' % (self._kodi.localize(30301).format(**channel), datelong)
plot = '%s\n%s' % (self._kodi.localize(30301, **channel), datelong)
channel_items.append(TitleItem(
title=channel.get('label'),
path=self._kodi.url_for('tvguide', date=date, channel=channel.get('name')),
Expand Down
16 changes: 8 additions & 8 deletions resources/lib/vrtapihelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,12 +400,12 @@ def episode_to_listitem(self, episode, program, cache_file, titletype):
# Only display when a video disappears if it is within the next 3 months
if metadata.offtime is not None and (metadata.offtime - now).days < 93:
# Show date when episode is removed
plot_meta += self._kodi.localize(30202).format(date=self._kodi.localize_dateshort(metadata.offtime))
plot_meta += self._kodi.localize(30202, date=self._kodi.localize_dateshort(metadata.offtime))
# Show the remaining days/hours the episode is still available
if (metadata.offtime - now).days > 0:
plot_meta += self._kodi.localize(30203).format(days=(metadata.offtime - now).days)
plot_meta += self._kodi.localize(30203, days=(metadata.offtime - now).days)
else:
plot_meta += self._kodi.localize(30204).format(hours=int((metadata.offtime - now).seconds / 3600))
plot_meta += self._kodi.localize(30204, hours=int((metadata.offtime - now).seconds / 3600))

if plot_meta:
metadata.plot = '%s\n%s' % (plot_meta, metadata.plot)
Expand Down Expand Up @@ -638,17 +638,17 @@ def get_channel_items(self, channels=None, live=True):
path = self._kodi.url_for('play_id', video_id=channel.get('live_stream_id'))
elif channel.get('live_stream'):
path = self._kodi.url_for('play_url', video_url=channel.get('live_stream'))
label = self._kodi.localize(30101).format(**channel)
label = self._kodi.localize(30101, **channel)
# A single Live channel means it is the entry for channel's TV Show listing, so make it stand out
if channels and len(channels) == 1:
label = '[B]%s[/B]' % label
is_playable = True
if channel.get('name') in ['een', 'canvas', 'ketnet']:
if self._showfanart:
fanart = self.get_live_screenshot(channel.get('name', fanart))
plot = '%s\n\n%s' % (self._kodi.localize(30102).format(**channel), _tvguide.live_description(channel.get('name')))
plot = '%s\n\n%s' % (self._kodi.localize(30102, **channel), _tvguide.live_description(channel.get('name')))
else:
plot = self._kodi.localize(30102).format(**channel)
plot = self._kodi.localize(30102, **channel)
# NOTE: Playcount is required to not have live streams as "Watched"
info_dict = dict(title=label, plot=plot, studio=channel.get('studio'), mediatype='video', playcount=0, duration=0)
stream_dict = dict(duration=0)
Expand Down Expand Up @@ -686,11 +686,11 @@ def get_youtube_items(self, channels=None, live=True):

if channel.get('youtube'):
path = channel.get('youtube')
label = self._kodi.localize(30103).format(**channel)
label = self._kodi.localize(30103, **channel)
# A single Live channel means it is the entry for channel's TV Show listing, so make it stand out
if channels and len(channels) == 1:
label = '[B]%s[/B]' % label
plot = self._kodi.localize(30104).format(**channel)
plot = self._kodi.localize(30104, **channel)
# NOTE: Playcount is required to not have live streams as "Watched"
info_dict = dict(title=label, plot=plot, studio=channel.get('studio'), mediatype='video', playcount=0)
context_menu = [(self._kodi.localize(30413), 'RunPlugin(%s)' % self._kodi.url_for('delete_cache', cache_file='channel.%s.json' % channel))]
Expand Down
2 changes: 1 addition & 1 deletion resources/lib/vrtplayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ def play_episode_by_air_date(self, channel, start_date, end_date):
''' Play an episode of a program given the channel and the air date in iso format (2019-07-06T19:35:00) '''
video = self._apihelper.get_episode_by_air_date(channel, start_date, end_date)
if video and video.get('video_title'):
self._kodi.show_ok_dialog(message=self._kodi.localize(30986) % video.get('video_title'))
self._kodi.show_ok_dialog(message=self._kodi.localize(30986, title=video.get('video_title')))
self._kodi.end_of_directory()
return
if not video:
Expand Down
38 changes: 38 additions & 0 deletions test/test_kodi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-

# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

# pylint: disable=missing-docstring

from __future__ import absolute_import, division, print_function, unicode_literals
import unittest

from resources.lib import kodiwrapper

xbmc = __import__('xbmc')
xbmcaddon = __import__('xbmcaddon')
xbmcgui = __import__('xbmcgui')
xbmcplugin = __import__('xbmcplugin')
xbmcvfs = __import__('xbmcvfs')


class KodiTests(unittest.TestCase):

_kodi = kodiwrapper.KodiWrapper(None)

def test_localize(self):
msg = self._kodi.localize(30958)
self.assertEqual(msg, "There is a problem with this VRT NU {protocol} stream. Try again with {component} {state} or try to play this program from the VRT NU website. Please report this problem at https://www.vrt.be/vrtnu/help/") # noqa
print(msg)

msg = self._kodi.localize(30958, component='Widevine DRM', state='enabled')
self.assertEqual(msg, "There is a problem with this VRT NU {protocol} stream. Try again with Widevine DRM enabled or try to play this program from the VRT NU website. Please report this problem at https://www.vrt.be/vrtnu/help/") # noqa
print(msg)

msg = self._kodi.localize(30958, protocol='MPEG-DASH', component='Widevine DRM', state='enabled')
self.assertEqual(msg, "There is a problem with this VRT NU MPEG-DASH stream. Try again with Widevine DRM enabled or try to play this program from the VRT NU website. Please report this problem at https://www.vrt.be/vrtnu/help/") # noqa
print(msg)


if __name__ == '__main__':
unittest.main()

0 comments on commit 85d6c48

Please sign in to comment.