Skip to content

Commit e79ca25

Browse files
committed
Add support for localization API of npf-renderer
1 parent 3dac874 commit e79ca25

File tree

4 files changed

+143
-7
lines changed

4 files changed

+143
-7
lines changed
+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Copyright (C) 2023 Syeopite
2+
# This file is distributed under the same license as the Priviblur project.
3+
# syeopite <syeopite@syeopite.dev>, 2023
4+
#
5+
msgid ""
6+
msgstr ""
7+
"Project-Id-Version: Priviblur v0.3.0-dev\n"
8+
"Report-Msgid-Bugs-To: https://github.com/syeopite/priviblur/issues\n"
9+
"POT-Creation-Date: 2023-11-16 00:07-0800\n"
10+
"PO-Revision-Date: 2024-06-29 04:09+0000\n"
11+
"Last-Translator: syeopite <syeopite@users.noreply.hosted.weblate.org>\n"
12+
"Language-Team: English <https://hosted.weblate.org/projects/priviblur/"
13+
"translations/en/>\n"
14+
"Language: en\n"
15+
"MIME-Version: 1.0\n"
16+
"Content-Type: text/plain; charset=utf-8\n"
17+
"Content-Transfer-Encoding: 8bit\n"
18+
"Plural-Forms: nplurals=2; plural=n != 1;\n"
19+
"X-Generator: Weblate 5.7-dev\n"
20+
21+
msgid "asker_with_no_attribution"
22+
msgstr "Anonymous"
23+
24+
msgid "asker_and_ask_verb"
25+
msgstr "{name} asked"
26+
27+
msgid "unsupported_block_header"
28+
msgstr "Unsupported NPF block"
29+
30+
msgid "unsupported_block_description"
31+
msgstr "Placeholder for the unsupported \"{block}\" type NPF block Please report me over at https://github.com/syeopite/npf-renderer"
32+
33+
msgid "generic_image_alt_text"
34+
msgstr "image"
35+
36+
msgid "link_block_poster_alt_text"
37+
msgstr "Preview image for \"{site}\""
38+
39+
msgid "link_block_fallback_embeds_are_disabled"
40+
msgstr "Embeds are disabled"
41+
42+
msgid "error_video_link_block_fallback_heading"
43+
msgstr "Error: unable to render video block"
44+
45+
msgid "video_link_block_fallback_description"
46+
msgstr "Please click me to watch on the original site"
47+
48+
msgid "error_link_block_fallback_native_video_player_non_tumblr_source"
49+
msgstr "Error: non-tumblr source for video player"
50+
51+
msgid "fallback_audio_block_thumbnail_alt_text"
52+
msgstr "Album art"
53+
54+
msgid "error_audio_link_block_fallback_heading"
55+
msgstr "Error: unable to render audio block"
56+
57+
msgid "audio_link_block_fallback_description"
58+
msgstr "Please click me to listen on the original site"
59+
60+
msgid "error_link_block_fallback_native_audio_player_non_tumblr_source"
61+
msgstr "Error: non-tumblr source for audio player"
62+
63+
msgid "poll_total_votes"
64+
msgid_plural "poll_total_votes_plural"
65+
msgstr[0] "{votes} vote"
66+
msgstr[1] "{votes} votes"
67+
68+
msgid "poll_remaining_time"
69+
msgstr "{duration} remaining"
70+
71+
msgid "poll_ended_on"
72+
msgstr "Ended on: {ended_date}"
73+
74+
msgid "post_attribution"
75+
msgstr "From {0}"
76+
77+
msgid "blog_attribution"
78+
msgstr "Created by {0}"
79+
80+
msgid "app_attribution"
81+
msgstr "View on {0}"
82+
83+
msgid "unsupported_attribution"
84+
msgstr "Attributed via an unsupported (\"{0}\") attribution type. Please report this over at https://github.com/syeopite/npf-renderer"

src/helpers/ext_npf_renderer.py

+1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ def __init__(
123123
if request:
124124
# Asking to expand a post is the reverse of asking to truncate a post
125125
initialization_arguments["truncate"] = not request.ctx.preferences.expand_posts
126+
initialization_arguments["localizer"] = request.app.ctx.LANGUAGES[request.ctx.language].npf_renderer_localizer
126127

127128
super().__init__(**initialization_arguments)
128129

src/i18n/i18n.py

+57-6
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,58 @@
11
import sys
22
import gettext
33
import typing
4+
import functools
45

56
import sanic
7+
import babel
8+
import babel.dates
9+
import npf_renderer
610

711
from .i18n_data import LOCALE_DATA
812

913

14+
class NPFRendererGettextFallback(gettext.NullTranslations):
15+
def gettext(self, message):
16+
return npf_renderer.DEFAULT_LOCALIZATION[message]
17+
18+
def ngettext(self, msgid1: str, msgid2: str, n: int) -> str:
19+
return npf_renderer.DEFAULT_LOCALIZATION[msgid1]
20+
21+
22+
class NPFRendererLocalizer:
23+
def __init__(self, language, locale):
24+
self.language = language
25+
self.locale = locale
26+
27+
self.format_functions = {
28+
"format_duration_func": functools.partial(babel.dates.format_timedelta, threshold=1.1, locale=language),
29+
"format_datetime_func": functools.partial(babel.dates.format_datetime, format=f"short", locale=language),
30+
}
31+
32+
def __getitem__(self, key : str):
33+
# Starts with format_
34+
if key[:7] == "format_":
35+
return self.format_functions[key]
36+
# Starts with plural_
37+
elif key[:7] == "plural_":
38+
return lambda number : translate(self.language, key[7:], number, priviblur_translations=False)
39+
40+
translate("en_US", "poll_remaining_time", priviblur_translations=False)
41+
42+
return translate(self.language, key, priviblur_translations=False)
43+
44+
1045
class Language:
1146
"""Stores metadata about supported translations"""
12-
def __init__(self, locale, gettext_instance,) -> None:
47+
def __init__(self, locale, priviblur_gettext, npf_renderer_gettext) -> None:
1348
self.locale = locale
1449

15-
self.priviblur_translations = gettext_instance
50+
self.babel_locale = babel.Locale.parse(locale)
51+
52+
self.priviblur_translations = priviblur_gettext
53+
54+
self.npf_renderer_translations = npf_renderer_gettext
55+
self.npf_renderer_localizer = NPFRendererLocalizer(locale, self.babel_locale)
1656

1757
self.name, self.translation_percentage = LOCALE_DATA[locale]
1858

@@ -30,8 +70,11 @@ def initialize_locales() -> typing.Mapping[str, Language]:
3070

3171
priviblur_english_instance = gettext.translation("priviblur", localedir="locales", languages=("en_US",))
3272

73+
npf_renderer_english_instance = gettext.translation("npf_renderer", localedir="locales", languages=("en_US",))
74+
npf_renderer_english_instance.add_fallback(NPFRendererGettextFallback())
75+
3376
languages = {
34-
"en_US": Language("en_US", priviblur_english_instance)
77+
"en_US": Language("en_US", priviblur_english_instance, npf_renderer_english_instance)
3578
}
3679

3780
for locale in SUPPORTED_LANGUAGES:
@@ -41,7 +84,12 @@ def initialize_locales() -> typing.Mapping[str, Language]:
4184
instance = gettext.translation("priviblur", localedir="locales", languages=(locale,))
4285
instance.add_fallback(priviblur_english_instance)
4386

44-
languages[locale] = Language(locale, instance)
87+
try:
88+
npf_renderer_instance = gettext.translation("npf_renderer", localedir="locales", languages=(locale,))
89+
except FileNotFoundError:
90+
npf_renderer_instance = npf_renderer_english_instance
91+
92+
languages[locale] = Language(locale, instance, npf_renderer_instance)
4593
except FileNotFoundError as e:
4694
print(
4795
'Error: Unable to find locale files. '
@@ -56,10 +104,13 @@ def initialize_locales() -> typing.Mapping[str, Language]:
56104

57105

58106
def translate(language : str, id : str, number : int | float | None = None,
59-
substitution : str | dict | None = None) -> str:
107+
substitution : str | dict | None = None, priviblur_translations : bool = True) -> str:
60108
app = sanic.Sanic.get_app("Priviblur")
61109

62-
gettext_instance = app.ctx.LANGUAGES[language].priviblur_translations
110+
if priviblur_translations:
111+
gettext_instance = app.ctx.LANGUAGES[language].priviblur_translations
112+
else:
113+
gettext_instance = app.ctx.LANGUAGES[language].npf_renderer_translations
63114

64115
if number is not None:
65116
translated = gettext_instance.ngettext(id, f"{id}_plural", number)

src/preferences.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import dataclasses
22
import urllib.parse
33

4-
from .helpers.i18n import SUPPORTED_LANGUAGES
4+
from .i18n import SUPPORTED_LANGUAGES
55

66
VERSION = 1
77

0 commit comments

Comments
 (0)