mirror of
https://git.sr.ht/~cadence/bibliogram
synced 2025-12-14 10:35:07 +00:00
Create initial language support
Create support for languages, then reformat user, home, and post pages to use it, and create en and en-us language files.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
const constants = require("../../lib/constants")
|
||||
const lang = require("../../lang")
|
||||
const switcher = require("../../lib/utils/torswitcher")
|
||||
const {fetchUser, getOrFetchShortcode, userRequestCache, history, assistantSwitcher} = require("../../lib/collectors")
|
||||
const {render, redirect, getStaticURL} = require("pinski/plugins")
|
||||
@@ -112,7 +113,8 @@ module.exports = [
|
||||
username,
|
||||
expiresMinutes: userRequestCache.getTtl("user/"+username, 1000*60),
|
||||
getStaticURL,
|
||||
settings
|
||||
settings,
|
||||
lang
|
||||
})
|
||||
}
|
||||
} else if (error === constants.symbols.extractor_results.AGE_RESTRICTED) {
|
||||
@@ -179,7 +181,7 @@ module.exports = [
|
||||
contentType: "application/json",
|
||||
content: {
|
||||
title: getPageTitle(post),
|
||||
html: pugCache.get("pug/fragments/post.pug").web({post, settings, getStaticURL})
|
||||
html: pugCache.get("pug/fragments/post.pug").web({lang, post, settings, getStaticURL})
|
||||
}
|
||||
}
|
||||
}).catch(error => {
|
||||
|
||||
@@ -57,7 +57,7 @@ class ElemJS {
|
||||
event(name, callback) {
|
||||
this.element.addEventListener(name, event => callback(event))
|
||||
}
|
||||
child(toAdd, position) {
|
||||
child(toAdd, position = undefined) {
|
||||
if (typeof(toAdd) == "object") {
|
||||
toAdd.parent = this;
|
||||
if (typeof(position) == "number" && position >= 0) {
|
||||
|
||||
@@ -75,7 +75,7 @@ class NextPage extends FreezeWidth {
|
||||
fetch() {
|
||||
if (this.fetching) return
|
||||
this.fetching = true
|
||||
this.freeze("Loading...")
|
||||
this.freeze(this.element.getAttribute("data-loading-text"))
|
||||
const type = this.element.getAttribute("data-type")
|
||||
|
||||
return fetch(`/fragment/user/${this.element.getAttribute("data-username")}/${this.nextPageNumber}?type=${type}`).then(res => res.text()).then(text => {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
//- Needs post
|
||||
|
||||
- const ll = lang.get(settings.language)
|
||||
|
||||
include ../includes/post.pug
|
||||
|
||||
+post(post, true)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
//- Needs user, selectedTimeline, url, type
|
||||
|
||||
- const ll = lang.get(settings.language)
|
||||
|
||||
include ../includes/timeline_page.pug
|
||||
include ../includes/next_page_button.pug
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
//- Needs rssEnabled, allUnblocked, torAvailable, hasPrivacyPolicy, onionLocation
|
||||
|
||||
- const ll = lang.get(settings.language)
|
||||
|
||||
doctype html
|
||||
html
|
||||
head
|
||||
@@ -13,57 +15,53 @@ html
|
||||
.go-sections-container
|
||||
.go-sections
|
||||
section
|
||||
h2.title Go to profile
|
||||
h2.title= ll.go_to_profile
|
||||
form(method="get" action="/u").pair-entry
|
||||
input(type="text" name="u" placeholder="Username or URL").text
|
||||
input(type="submit" value="Go").button
|
||||
input(type="text" name="u" placeholder=ll.go_username_or_url).text
|
||||
input(type="submit" value=ll.go_button).button
|
||||
section
|
||||
h2.title Go to post
|
||||
h2.title= ll.go_to_post
|
||||
form(method="get" action="/p").pair-entry
|
||||
input(type="text" name="p" placeholder="Shortcode or URL").text
|
||||
input(type="submit" value="Go").button
|
||||
input(type="text" name="p" placeholder=ll.go_shortcode_or_url).text
|
||||
input(type="submit" value=ll.go_button).button
|
||||
|
||||
.about-container
|
||||
section.about
|
||||
h2 About Bibliogram
|
||||
p.
|
||||
Bibliogram is a website that takes data from Instagram's public profile views and puts it into
|
||||
a friendlier page that loads faster, gives downloadable images, eliminates ads,
|
||||
generates RSS feeds, and doesn't urge you to sign up. #[a(href=(constants.featured_profiles.length ? "#featured-profiles" : "/u/instagram")).example-link See an example.]
|
||||
p.
|
||||
Bibliogram does #[em not] allow you to anonymously post, like, comment, follow, or view private profiles.
|
||||
It does not preserve deleted posts.
|
||||
|
||||
h2 About this instance
|
||||
h2= ll.about_bibliogram_header
|
||||
!= ll.pug_about_bibliogram_content(constants.featured_profiles.length)
|
||||
h2= ll.about_this_instance_header
|
||||
ul
|
||||
if onionLocation
|
||||
li: a(href=onionLocation) Onion site available
|
||||
li: a(href=settingsReferrer) Settings
|
||||
li: a(href=onionLocation)= ll.onion_site_available
|
||||
li: a(href=settingsReferrer)= ll.t_settings
|
||||
if hasPrivacyPolicy
|
||||
li: a(href="/privacy") Privacy policy
|
||||
li: a(href="/privacy")= ll.t_privacy_policy
|
||||
else
|
||||
li Owner has not written a privacy policy
|
||||
li= ll.has_not_written_privacy_policy
|
||||
if allUnblocked
|
||||
li Instance is not blocked
|
||||
li= ll.instance_not_blocked
|
||||
else
|
||||
li: a(href="https://git.sr.ht/~cadence/bibliogram-docs/tree/master/docs/Instagram%20rate%20limits.md#tldr-what-does-it-mean-if-an-instance-is-blocked") Instance is partially blocked
|
||||
li RSS feeds are #{rssEnabled ? "enabled" : "disabled"}
|
||||
li: a(href="https://git.sr.ht/~cadence/bibliogram-docs/tree/master/docs/Instagram%20rate%20limits.md#tldr-what-does-it-mean-if-an-instance-is-blocked")= ll.instance_partially_blocked
|
||||
if rssEnabled
|
||||
li= ll.rss_enabled
|
||||
else
|
||||
li= ll.rss_disabled
|
||||
|
||||
h2 External links
|
||||
h2= ll.external_links_header
|
||||
ul
|
||||
-
|
||||
const links = [
|
||||
["https://sr.ht/~cadence/bibliogram/", "Code on sourcehut", "noopener noreferrer"],
|
||||
["https://matrix.to/#/#bibliogram:matrix.org", "Discussion room on Matrix", "noopener noreferrer"],
|
||||
["https://git.sr.ht/~cadence/bibliogram-docs/tree/master/docs/Instances.md", "Other Bibliogram instances", "noopener noreferrer"],
|
||||
["https://cadence.moe/about/contact", "Contact the developer", "noopener noreferrer"]
|
||||
["https://sr.ht/~cadence/bibliogram/", ll.source_link, "noopener noreferrer"],
|
||||
["https://matrix.to/#/#bibliogram:matrix.org", ll.matrix_link, "noopener noreferrer"],
|
||||
["https://git.sr.ht/~cadence/bibliogram-docs/tree/master/docs/Instances.md", ll.instances_link, "noopener noreferrer"],
|
||||
["https://cadence.moe/about/contact", ll.contact_link, "noopener noreferrer"]
|
||||
]
|
||||
each entry in links
|
||||
li: a(href!=entry[0] target="_blank" rel=entry[2])= entry[1]
|
||||
|
||||
if constants.featured_profiles.length
|
||||
.featured-profiles#featured-profiles
|
||||
h2.featured-profiles-header Featured profiles
|
||||
h2.featured-profiles-header= ll.featured_profiles_header
|
||||
|
||||
table.featured-profile-table
|
||||
tbody
|
||||
@@ -73,7 +71,5 @@ html
|
||||
td= profile.description
|
||||
|
||||
details
|
||||
summary What's this?
|
||||
.details-content
|
||||
p The owner of this website personally thinks that these profiles are interesting.
|
||||
p These are not endorsements from the Bibliogram project.
|
||||
summary= ll.featured_profiles_whats_this
|
||||
.details-content= ll.html_featured_profiles_disclaimer
|
||||
|
||||
@@ -4,8 +4,14 @@ mixin next_page_button(user, selectedTimeline, url, type)
|
||||
-
|
||||
const nu = new URL(url)
|
||||
nu.searchParams.set("page", selectedTimeline.pages.length+1)
|
||||
a(href=`${nu.search}#page-${selectedTimeline.pages.length+1}` data-page=(selectedTimeline.pages.length+1) data-username=(user.data.username) data-type=type)#next-page.next-page Next page
|
||||
a(
|
||||
href=`${nu.search}#page-${selectedTimeline.pages.length+1}`
|
||||
data-page=(selectedTimeline.pages.length+1)
|
||||
data-username=(user.data.username)
|
||||
data-type=type
|
||||
data-loading-text=ll.next_page_button_loading
|
||||
)#next-page.next-page= ll.next_page_button
|
||||
else
|
||||
div
|
||||
div.page-number.no-more-pages
|
||||
span.number No more posts.
|
||||
span.number= ll.no_more_posts_notice
|
||||
|
||||
@@ -39,7 +39,7 @@ mixin post(post, headerWithNavigation)
|
||||
if caption
|
||||
p.description= caption
|
||||
p.description
|
||||
span Posted on #[time(datetime=post.date.toISOString() data-local-date)= post.getDisplayDate()].
|
||||
span!= ll.pug_post_timestamp({post})
|
||||
|
||||
section.images-gallery
|
||||
for entry in post.children
|
||||
|
||||
@@ -5,7 +5,7 @@ mixin timeline_page(page, pageIndex)
|
||||
- const pageNumber = pageIndex + 1
|
||||
if pageNumber > 1
|
||||
header.page-number(id=`page-${pageNumber}`)
|
||||
span.number Page #{pageNumber}
|
||||
span.number= ll.fn_page_divider(pageNumber)
|
||||
|
||||
.timeline-inner(class=`${settings.timeline_columns}-columns`)
|
||||
- const suggestedSize = 260 //- from css :(
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
//- Needs website_origin, title, post, settings
|
||||
|
||||
- const ll = lang.get(settings.language)
|
||||
|
||||
include includes/post
|
||||
|
||||
doctype html
|
||||
|
||||
@@ -45,7 +45,7 @@ html
|
||||
h1 Settings
|
||||
|
||||
+fieldset("Features")
|
||||
+select("language", "Language", true, [
|
||||
+select("language", "Language", false, [
|
||||
{value: "en", text: "English (International)"},
|
||||
{value: "en-us", text: "English (US)"}
|
||||
])
|
||||
|
||||
@@ -5,13 +5,14 @@ include includes/next_page_button.pug
|
||||
include includes/display_structured
|
||||
include includes/feed_link
|
||||
|
||||
- const ll = lang.get(settings.language)
|
||||
- const numberFormat = new Intl.NumberFormat().format
|
||||
|
||||
mixin selector-button(text, selectorType, urlSuffix)
|
||||
a(href=(type !== selectorType && `/u/${user.data.username}${urlSuffix}`) class=(type === selectorType && "active")).selector= text
|
||||
|
||||
mixin verified-badge(classes)
|
||||
img.verified-badge(class=classes src=getStaticURL("html", "/static/img/verified.svg") width=19 height=19 alt="Verified." title="Verified")
|
||||
img.verified-badge(class=classes src=getStaticURL("html", "/static/img/verified.svg") width=19 height=19 alt=ll.verified_badge_alt title=ll.verified_badge_title)
|
||||
|
||||
doctype html
|
||||
html
|
||||
@@ -42,7 +43,7 @@ html
|
||||
a(href="/").nav-icon-link
|
||||
img(src="/static/img/logo-circle-min.svg" alt="Bibliogram").logo
|
||||
a(href=settingsReferrer).nav-icon-link
|
||||
img(src="/static/img/settings.svg" alt="Settings").settings
|
||||
img(src="/static/img/settings.svg" alt=ll.t_settings).settings
|
||||
.main-divider
|
||||
header.profile-overview
|
||||
.profile-sticky
|
||||
@@ -71,12 +72,18 @@ html
|
||||
p.website
|
||||
a(href=userURL)= userURL
|
||||
if user.posts != undefined
|
||||
div.profile-counter #[span(data-numberformat=user.posts).count #{numberFormat(user.posts)}] posts
|
||||
div.profile-counter
|
||||
| #[span(data-numberformat=user.posts).count #{numberFormat(user.posts)} ]
|
||||
= ll.post_counter_label
|
||||
if followerCountsAvailable
|
||||
if user.following != undefined
|
||||
div.profile-counter #[span(data-numberformat=user.following).count #{numberFormat(user.following)}] following
|
||||
div.profile-counter
|
||||
| #[span(data-numberformat=user.following).count #{numberFormat(user.following)} ]
|
||||
= ll.outgoing_follows_counter_label
|
||||
if user.followedBy != undefined
|
||||
div.profile-counter #[span(data-numberformat=user.followedBy).count #{numberFormat(user.followedBy)}] followed by
|
||||
div.profile-counter
|
||||
| #[span(data-numberformat=user.followedBy).count #{numberFormat(user.followedBy)} ]
|
||||
= ll.incoming_follows_counter_label
|
||||
else
|
||||
div.profile-counter.not-available Followers not available.
|
||||
.links
|
||||
@@ -86,15 +93,15 @@ html
|
||||
a(rel="noreferrer noopener" href=`https://www.instagram.com/${user.data.username}` target="_blank") instagram.com
|
||||
section.bibliogram-meta
|
||||
.links
|
||||
a(href="/") Home
|
||||
a(href=settingsReferrer) Settings
|
||||
a(href="/")= ll.t_home
|
||||
a(href=settingsReferrer)= ll.t_settings
|
||||
|
||||
- const hasPosts = !user.data.is_private && selectedTimeline.pages.length && selectedTimeline.pages[0].length
|
||||
.timeline-section
|
||||
.selector-container
|
||||
+selector-button("Timeline", "timeline", "")
|
||||
+selector-button(ll.tab_timeline, "timeline", "")
|
||||
if user.data.has_channel !== false
|
||||
+selector-button("IGTV", "igtv", "/channel")
|
||||
+selector-button(ll.tab_igtv, "igtv", "/channel")
|
||||
|
||||
main(class=hasPosts ? "" : "no-posts")#timeline.timeline
|
||||
if hasPosts
|
||||
@@ -106,6 +113,6 @@ html
|
||||
div.page-number
|
||||
span.number
|
||||
if user.data.is_private
|
||||
| Profile is private.
|
||||
= ll.profile_is_private_notice
|
||||
else
|
||||
| No posts.
|
||||
= ll.no_posts_notice
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const {Pinski} = require("pinski")
|
||||
const {subdirs} = require("node-dir")
|
||||
const constants = require("../lib/constants")
|
||||
const lang = require("../lang")
|
||||
|
||||
const passthrough = require("./passthrough")
|
||||
|
||||
@@ -64,7 +65,7 @@ subdirs("pug", async (err, dirs) => {
|
||||
|
||||
const plugins = require("pinski/plugins")
|
||||
plugins.setInstance(pinski)
|
||||
Object.assign(pinski.pugDefaultLocals, {constants})
|
||||
Object.assign(pinski.pugDefaultLocals, {constants, lang})
|
||||
Object.assign(passthrough, pinski.getExports())
|
||||
|
||||
console.log("[.] Server started")
|
||||
|
||||
Reference in New Issue
Block a user