Skip to content

Commit fcdd04d

Browse files
authored
Integrate pyformat with localize() (#384)
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.
1 parent 4becfc0 commit fcdd04d

File tree

10 files changed

+86
-37
lines changed

10 files changed

+86
-37
lines changed

resources/language/resource.language.en_gb/strings.po

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -634,11 +634,11 @@ msgid "Please increase the maximum bandwidth. Maximum bandwidth is set to {max}
634634
msgstr ""
635635

636636
msgctxt "#30958"
637-
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/"
637+
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/"
638638
msgstr ""
639639

640640
msgctxt "#30959"
641-
msgid "and Widevine DRM"
641+
msgid "InputStream Adaptive and Widevine DRM"
642642
msgstr ""
643643

644644
msgctxt "#30960"
@@ -650,7 +650,7 @@ msgid "enabled"
650650
msgstr ""
651651

652652
msgctxt "#30962"
653-
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/"
653+
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/"
654654
msgstr ""
655655

656656
msgctxt "#30965"
@@ -678,7 +678,7 @@ msgid "Failed to get favorites token from VRT NU"
678678
msgstr ""
679679

680680
msgctxt "#30976"
681-
msgid "Failed to (un)follow program '%s' at VRT NU"
681+
msgid "Failed to (un)follow program '{program}' at VRT NU"
682682
msgstr ""
683683

684684
msgctxt "#30978"
@@ -714,7 +714,7 @@ msgid "Successfully cleared VRT tokens."
714714
msgstr ""
715715

716716
msgctxt "#30986"
717-
msgid "No on demand stream available for %s."
717+
msgid "No on demand stream available for {title}."
718718
msgstr ""
719719

720720
msgctxt "#30990"

resources/language/resource.language.nl_nl/strings.po

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -526,12 +526,12 @@ msgid "Please increase the maximum bandwidth. Maximum bandwidth is set to {max}
526526
msgstr "Verhoog de maximale bandbreedte alstublieft. De maximale bandbreedte is ingesteld op {max} kbps, maar deze stream heeft minimum {min} kbps nodig."
527527

528528
msgctxt "#30958"
529-
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/"
530-
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/"
529+
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/"
530+
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/"
531531

532532
msgctxt "#30959"
533-
msgid "and Widevine DRM"
534-
msgstr "en Widevine DRM"
533+
msgid "InputStream Adaptive and Widevine DRM"
534+
msgstr "InputStream Adaptive en Widevine DRM"
535535

536536
msgctxt "#30960"
537537
msgid "disabled"
@@ -542,8 +542,8 @@ msgid "enabled"
542542
msgstr "ingeschakeld"
543543

544544
msgctxt "#30962"
545-
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/"
546-
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/"
545+
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/"
546+
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/"
547547

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

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

576576
msgctxt "#30978"
577577
msgid "Welcome to VRT NU add-on v2.0.0"
@@ -606,8 +606,8 @@ msgid "Successfully cleared VRT tokens."
606606
msgstr "VRT tokens werden verwijderd."
607607

608608
msgctxt "#30986"
609-
msgid "No on demand stream available for %s."
610-
msgstr "Geen on demand stream beschikbaar voor %s"
609+
msgid "No on demand stream available for {title}."
610+
msgstr "Geen on demand stream beschikbaar voor {title}"
611611

612612
msgctxt "#30990"
613613
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."

resources/lib/favorites.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ def set_favorite(self, program, title, value=True):
6565

6666
xvrttoken = self._tokenresolver.get_xvrttoken(token_variant='user')
6767
if xvrttoken is None:
68-
self._kodi.show_notification(message=self._kodi.localize(30975))
6968
self._kodi.log_error('Failed to get favorites token from VRT NU')
69+
self._kodi.show_notification(message=self._kodi.localize(30975))
7070
return False
7171

7272
headers = {
@@ -81,8 +81,8 @@ def set_favorite(self, program, title, value=True):
8181
req = Request('https://video-user-data.vrt.be/favorites/%s' % self.uuid(program), data=data, headers=headers)
8282
result = urlopen(req)
8383
if result.getcode() != 200:
84-
self._kodi.show_notification(message=self._kodi.localize(30976) % program)
85-
self._kodi.log_error("Failed to (un)follow program '%s' at VRT NU" % program)
84+
self._kodi.log_error("Failed to (un)follow program '{program}' at VRT NU".format(program=program))
85+
self._kodi.show_notification(message=self._kodi.localize(30976, program=program))
8686
return False
8787
# NOTE: Updates to favorites take a longer time to take effect, so we keep our own cache and use it
8888
self._favorites[self.uuid(program)] = dict(value=payload)

resources/lib/kodiwrapper.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,13 @@ def has_socks():
100100
return has_socks.installed
101101

102102

103+
class SafeDict(dict):
104+
''' A safe dictionary implementation that does not break down on missing keys '''
105+
def __missing__(self, key):
106+
''' Replace missing keys with the original placeholder '''
107+
return '{' + key + '}'
108+
109+
103110
class KodiWrapper:
104111
''' A wrapper around all Kodi functionality '''
105112

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

294-
def localize(self, string_id):
295-
''' Return the translated string from the .po language files '''
301+
def localize(self, string_id, **kwargs):
302+
''' Return the translated string from the .po language files, optionally translating variables '''
303+
if kwargs:
304+
import string
305+
return string.Formatter().vformat(self._addon.getLocalizedString(string_id), (), SafeDict(**kwargs))
306+
296307
return self._addon.getLocalizedString(string_id)
297308

298309
def localize_date(self, date, strftime):

resources/lib/search.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def search(self, keywords=None, page=None):
7474
self.add(keywords)
7575
search_items, sort, ascending, content = self._apihelper.get_search_items(keywords, page=page)
7676
if not search_items:
77-
self._kodi.show_ok_dialog(heading=self._kodi.localize(30098), message=self._kodi.localize(30099).format(keywords=keywords))
77+
self._kodi.show_ok_dialog(heading=self._kodi.localize(30098), message=self._kodi.localize(30099, keywords=keywords))
7878
self._kodi.end_of_directory()
7979
return
8080

resources/lib/streamservice.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -291,15 +291,15 @@ def _handle_bad_stream_error(self, protocol):
291291
'''
292292
# HLS AES DRM failed
293293
if protocol == 'hls_aes' and not self._kodi.supports_drm():
294-
message = self._kodi.localize(30962) % (protocol.upper(), self._kodi.kodi_version())
294+
message = self._kodi.localize(30962, protocol=protocol.upper(), version=self._kodi.kodi_version())
295295
elif protocol == 'hls_aes' and not self._kodi.has_inputstream_adaptive() and self._kodi.get_setting('usedrm', 'true') == 'false':
296-
message = self._kodi.localize(30958) % (protocol.upper(), 'InputStream Adaptive', self._kodi.localize(30959), self._kodi.localize(30961))
296+
message = self._kodi.localize(30958, protocol=protocol.upper(), component=self._kodi.localize(30959), state=self._kodi.localize(30961))
297297
elif protocol == 'hls_aes' and self._kodi.has_inputstream_adaptive():
298-
message = self._kodi.localize(30958) % (protocol.upper(), 'Widevine DRM', '', self._kodi.localize(30961))
298+
message = self._kodi.localize(30958, protocol=protocol.upper(), component='Widevine DRM', state=self._kodi.localize(30961))
299299
elif protocol == 'hls_aes' and self._kodi.get_setting('usedrm', 'true') == 'true':
300-
message = self._kodi.localize(30958) % (protocol.upper(), 'InputStream Adaptive', '', self._kodi.localize(30961))
300+
message = self._kodi.localize(30958, protocol=protocol.upper(), component='InputStream Adaptive', state=self._kodi.localize(30961))
301301
else:
302-
message = self._kodi.localize(30958) % (protocol.upper(), 'InputStream Adaptive', '', self._kodi.localize(30960))
302+
message = self._kodi.localize(30958, protocol=protocol.upper(), component='InputStream Adaptive', state=self._kodi.localize(30960))
303303
self._kodi.show_ok_dialog(message=message)
304304
self._kodi.end_of_directory()
305305

@@ -338,7 +338,7 @@ def _select_hls_substreams(self, master_hls_url, protocol):
338338
break
339339

340340
if stream_bandwidth > max_bandwidth and not hls_variant_url:
341-
message = self._kodi.localize(30057).format(max=max_bandwidth, min=stream_bandwidth)
341+
message = self._kodi.localize(30057, max=max_bandwidth, min=stream_bandwidth)
342342
self._kodi.show_ok_dialog(message=message)
343343
self._kodi.open_settings()
344344

resources/lib/tvguide.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ def show_channel_menu(self, date):
110110

111111
fanart = 'resource://resource.images.studios.coloured/%(studio)s.png' % channel
112112
thumb = 'resource://resource.images.studios.white/%(studio)s.png' % channel
113-
plot = '%s\n%s' % (self._kodi.localize(30301).format(**channel), datelong)
113+
plot = '%s\n%s' % (self._kodi.localize(30301, **channel), datelong)
114114
channel_items.append(TitleItem(
115115
title=channel.get('label'),
116116
path=self._kodi.url_for('tvguide', date=date, channel=channel.get('name')),

resources/lib/vrtapihelper.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -400,12 +400,12 @@ def episode_to_listitem(self, episode, program, cache_file, titletype):
400400
# Only display when a video disappears if it is within the next 3 months
401401
if metadata.offtime is not None and (metadata.offtime - now).days < 93:
402402
# Show date when episode is removed
403-
plot_meta += self._kodi.localize(30202).format(date=self._kodi.localize_dateshort(metadata.offtime))
403+
plot_meta += self._kodi.localize(30202, date=self._kodi.localize_dateshort(metadata.offtime))
404404
# Show the remaining days/hours the episode is still available
405405
if (metadata.offtime - now).days > 0:
406-
plot_meta += self._kodi.localize(30203).format(days=(metadata.offtime - now).days)
406+
plot_meta += self._kodi.localize(30203, days=(metadata.offtime - now).days)
407407
else:
408-
plot_meta += self._kodi.localize(30204).format(hours=int((metadata.offtime - now).seconds / 3600))
408+
plot_meta += self._kodi.localize(30204, hours=int((metadata.offtime - now).seconds / 3600))
409409

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

687687
if channel.get('youtube'):
688688
path = channel.get('youtube')
689-
label = self._kodi.localize(30103).format(**channel)
689+
label = self._kodi.localize(30103, **channel)
690690
# A single Live channel means it is the entry for channel's TV Show listing, so make it stand out
691691
if channels and len(channels) == 1:
692692
label = '[B]%s[/B]' % label
693-
plot = self._kodi.localize(30104).format(**channel)
693+
plot = self._kodi.localize(30104, **channel)
694694
# NOTE: Playcount is required to not have live streams as "Watched"
695695
info_dict = dict(title=label, plot=plot, studio=channel.get('studio'), mediatype='video', playcount=0)
696696
context_menu = [(self._kodi.localize(30413), 'RunPlugin(%s)' % self._kodi.url_for('delete_cache', cache_file='channel.%s.json' % channel))]

resources/lib/vrtplayer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ def play_episode_by_air_date(self, channel, start_date, end_date):
238238
''' Play an episode of a program given the channel and the air date in iso format (2019-07-06T19:35:00) '''
239239
video = self._apihelper.get_episode_by_air_date(channel, start_date, end_date)
240240
if video and video.get('video_title'):
241-
self._kodi.show_ok_dialog(message=self._kodi.localize(30986) % video.get('video_title'))
241+
self._kodi.show_ok_dialog(message=self._kodi.localize(30986, title=video.get('video_title')))
242242
self._kodi.end_of_directory()
243243
return
244244
if not video:

test/test_kodi.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# -*- coding: utf-8 -*-
2+
3+
# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
4+
5+
# pylint: disable=missing-docstring
6+
7+
from __future__ import absolute_import, division, print_function, unicode_literals
8+
import unittest
9+
10+
from resources.lib import kodiwrapper
11+
12+
xbmc = __import__('xbmc')
13+
xbmcaddon = __import__('xbmcaddon')
14+
xbmcgui = __import__('xbmcgui')
15+
xbmcplugin = __import__('xbmcplugin')
16+
xbmcvfs = __import__('xbmcvfs')
17+
18+
19+
class KodiTests(unittest.TestCase):
20+
21+
_kodi = kodiwrapper.KodiWrapper(None)
22+
23+
def test_localize(self):
24+
msg = self._kodi.localize(30958)
25+
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
26+
print(msg)
27+
28+
msg = self._kodi.localize(30958, component='Widevine DRM', state='enabled')
29+
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
30+
print(msg)
31+
32+
msg = self._kodi.localize(30958, protocol='MPEG-DASH', component='Widevine DRM', state='enabled')
33+
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
34+
print(msg)
35+
36+
37+
if __name__ == '__main__':
38+
unittest.main()

0 commit comments

Comments
 (0)