Browse Source

Merge pull request #5437 from pixelfed/staging

Staging
daniel 6 months ago
parent
commit
a034905b23
30 changed files with 995 additions and 514 deletions
  1. 1 1
      app/Http/Controllers/Api/ApiV1Controller.php
  2. BIN
      public/js/discover~hashtag.bundle.7455573dc9d2be1f.js
  3. BIN
      public/js/discover~hashtag.bundle.93ce902dca5b65e3.js
  4. BIN
      public/js/manifest.js
  5. BIN
      public/mix-manifest.json
  6. 319 308
      resources/assets/components/Hashtag.vue
  7. 189 0
      resources/lang/de/settings.php
  8. 39 1
      resources/lang/de/site.php
  9. 9 0
      resources/lang/de/web.php
  10. 195 0
      resources/lang/en/settings.php
  11. 39 1
      resources/lang/en/site.php
  12. 8 8
      resources/views/settings/accessibility.blade.php
  13. 12 12
      resources/views/settings/dataexport.blade.php
  14. 2 2
      resources/views/settings/developers.blade.php
  15. 5 5
      resources/views/settings/email.blade.php
  16. 27 27
      resources/views/settings/home.blade.php
  17. 1 1
      resources/views/settings/import/ig.blade.php
  18. 4 4
      resources/views/settings/labs.blade.php
  19. 9 9
      resources/views/settings/media.blade.php
  20. 17 17
      resources/views/settings/partial/sidebar.blade.php
  21. 8 8
      resources/views/settings/password.blade.php
  22. 31 31
      resources/views/settings/privacy.blade.php
  23. 20 20
      resources/views/settings/relationships/home.blade.php
  24. 10 10
      resources/views/settings/security.blade.php
  25. 8 8
      resources/views/settings/security/device-panel.blade.php
  26. 4 4
      resources/views/settings/security/log-panel.blade.php
  27. 10 10
      resources/views/settings/timeline.blade.php
  28. 21 20
      resources/views/site/about.blade.php
  29. 5 5
      resources/views/site/fediverse.blade.php
  30. 2 2
      resources/views/site/opensource.blade.php

+ 1 - 1
app/Http/Controllers/Api/ApiV1Controller.php

@@ -3497,7 +3497,7 @@ class ApiV1Controller extends Controller
             return [];
         }
 
-        $defaultCaption = '';
+        $defaultCaption = "";
         $content = $request->filled('status') ? strip_tags($request->input('status')) : $defaultCaption;
         $cw = $user->profile->cw == true ? true : $request->boolean('sensitive', false);
         $spoilerText = $cw && $request->filled('spoiler_text') ? $request->input('spoiler_text') : null;

BIN
public/js/discover~hashtag.bundle.7455573dc9d2be1f.js


BIN
public/js/discover~hashtag.bundle.93ce902dca5b65e3.js


BIN
public/js/manifest.js


BIN
public/mix-manifest.json


+ 319 - 308
resources/assets/components/Hashtag.vue

@@ -1,325 +1,336 @@
 <template>
-	<div class="hashtag-component">
-		<div class="container-fluid mt-3">
-			<div class="row">
-				<div class="col-md-3 d-md-block">
-					<sidebar :user="profile" />
-				</div>
-				<div class="col-md-9">
-					<div class="card border-0 shadow-sm mb-3" style="border-radius: 18px;">
-						<div class="card-body">
-							<div class="media align-items-center py-3">
-								<div class="media-body">
-									<p class="h3 text-break mb-0">
-										<span class="text-lighter">#</span>{{ hashtag.name }}
-									</p>
-									<p v-if="hashtag.count && hashtag.count > 100" class="mb-0 text-muted font-weight-bold">
-										{{ formatCount(hashtag.count) }} Posts
-									</p>
-								</div>
-								<template v-if="hashtag && hashtag.hasOwnProperty('following') && feed && feed.length">
-									<button
-										v-if="hashtag.following"
-										:disabled="followingLoading"
-										class="btn btn-light hashtag-follow border rounded-pill font-weight-bold py-1 px-4"
-										@click="unfollowHashtag()"
-										>
-										<b-spinner v-if="followingLoading" small />
-										<span v-else>
-											{{ $t('profile.unfollow') }}
-										</span>
-									</button>
-
-									<button
-										v-else
-										:disabled="followingLoading"
-										class="btn btn-primary hashtag-follow font-weight-bold rounded-pill py-1 px-4"
-										@click="followHashtag()"
-										>
-										<b-spinner v-if="followingLoading" small />
-										<span v-else>
-											{{ $t('profile.follow') }}
-										</span>
-									</button>
-								</template>
-							</div>
-
-						</div>
-					</div>
-
-					<template v-if="isLoaded && feedLoaded">
-						<div class="row mx-0 hashtag-feed">
-							<div class="col-6 col-md-4 col-lg-3 p-1" v-for="(status, index) in feed" :key="'tlob:'+index">
-								<a
-									class="card info-overlay card-md-border-0"
-									:href="statusUrl(status)"
-									@click.prevent="goToPost(status)">
-									<div class="square">
-										<div v-if="status.sensitive" class="square-content">
-											<div class="info-overlay-text-label">
-												<h5 class="text-white m-auto font-weight-bold">
-													<span>
-														<span class="far fa-eye-slash fa-lg p-2 d-flex-inline"></span>
-													</span>
-												</h5>
-											</div>
-											<blur-hash-canvas
-												width="32"
-												height="32"
-												:hash="status.media_attachments[0].blurhash"
-												/>
-										</div>
-										<div v-else class="square-content">
-											<blur-hash-image
-												width="32"
-												height="32"
-												:hash="status.media_attachments[0].blurhash"
-												:src="status.media_attachments[0].url"
-												/>
-										</div>
-										<span v-if="status.pf_type == 'photo:album'" class="float-right mr-3 post-icon"><i class="fas fa-images fa-2x"></i></span>
-										<span v-if="status.pf_type == 'video'" class="float-right mr-3 post-icon"><i class="fas fa-video fa-2x"></i></span>
-										<span v-if="status.pf_type == 'video:album'" class="float-right mr-3 post-icon"><i class="fas fa-film fa-2x"></i></span>
-										<div class="info-overlay-text">
-											<h5 class="text-white m-auto font-weight-bold">
-												<span>
-													<span class="far fa-comment fa-lg p-2 d-flex-inline"></span>
-													<span class="d-flex-inline">{{formatCount(status.reply_count)}}</span>
-												</span>
-											</h5>
-										</div>
-									</div>
-								</a>
-							</div>
-
-							<div v-if="canLoadMore" class="col-12">
-								<intersect @enter="enterIntersect">
-									<div class="d-flex justify-content-center py-5">
-										<b-spinner />
-									</div>
-								</intersect>
-
-								<!-- <div v-else class="ph-item">
-									<div class="ph-picture big"></div>
-								</div> -->
-							</div>
-						</div>
-
-						<div v-if="feedLoaded && !feed.length" class="row mx-0 hashtag-feed justify-content-center">
-							<div class="col-12 col-md-8 text-center">
-								<img src="/img/illustrations/dk-nature-man-monochrome.svg" class="img-fluid" style="opacity: 0.6;max-width:400px">
-								<p class="lead text-muted font-weight-bold">{{ $t('hashtags.emptyFeed') }}</p>
-							</div>
-						</div>
-					</template>
-
-					<template v-else>
-						<div class="row justify-content-center align-items-center pt-5 mt-5">
-							<b-spinner />
-						</div>
-					</template>
-				</div>
-			</div>
-			<drawer />
-		</div>
-	</div>
+    <div class="hashtag-component">
+        <div class="container-fluid mt-3">
+            <div class="row">
+                <div class="col-md-3 d-md-block">
+                    <sidebar :user="profile" />
+                </div>
+                <div class="col-md-9">
+                    <div class="card border-0 shadow-sm mb-3" style="border-radius: 18px;">
+                        <div class="card-body">
+                            <div class="media align-items-center py-3">
+                                <div class="media-body">
+                                    <p class="h3 text-break mb-0">
+                                        <span class="text-lighter">#</span>{{ hashtag.name }}
+                                    </p>
+                                    <p v-if="hashtag.count && hashtag.count > 100" class="mb-0 text-muted font-weight-bold">
+                                        {{ formatCount(hashtag.count) }} Posts
+                                    </p>
+                                </div>
+                                <template v-if="hashtag && hashtag.hasOwnProperty('following') && feed && feed.length">
+                                    <button
+                                    v-if="hashtag.following"
+                                    :disabled="followingLoading"
+                                    class="btn btn-light hashtag-follow border rounded-pill font-weight-bold py-1 px-4"
+                                    @click="unfollowHashtag()"
+                                    >
+                                    <b-spinner v-if="followingLoading" small />
+                                    <span v-else>
+                                        {{ $t('profile.unfollow') }}
+                                    </span>
+                                    </button>
+
+                                    <button
+                                        v-else
+                                        :disabled="followingLoading"
+                                        class="btn btn-primary hashtag-follow font-weight-bold rounded-pill py-1 px-4"
+                                        @click="followHashtag()">
+                                        <b-spinner v-if="followingLoading" small />
+                                        <span v-else>
+                                            {{ $t('profile.follow') }}
+                                        </span>
+                                    </button>
+                                </template>
+                            </div>
+                        </div>
+                    </div>
+
+                    <template v-if="isLoaded && feedLoaded">
+                        <div class="row mx-0 hashtag-feed">
+                            <div class="col-6 col-md-4 col-lg-3 p-1" v-for="(status, index) in feed" :key="'tlob:'+index">
+                                <a
+                                class="card info-overlay card-md-border-0"
+                                :href="statusUrl(status)"
+                                @click.prevent="goToPost(status)">
+                                <div class="square">
+                                    <div v-if="status.sensitive" class="square-content">
+                                        <div class="info-overlay-text-label">
+                                            <h5 class="text-white m-auto font-weight-bold">
+                                                <span>
+                                                    <span class="far fa-eye-slash fa-lg p-2 d-flex-inline"></span>
+                                                </span>
+                                            </h5>
+                                        </div>
+                                        <blur-hash-canvas
+                                        width="32"
+                                        height="32"
+                                        :hash="status.media_attachments[0].blurhash"
+                                        />
+                                    </div>
+                                    <div v-else class="square-content">
+                                        <blur-hash-image
+                                        width="32"
+                                        height="32"
+                                        :hash="status.media_attachments[0].blurhash"
+                                        :src="getMediaSource(status)"
+                                        />
+                                    </div>
+                                    <span v-if="status.pf_type == 'photo:album'" class="float-right mr-3 post-icon"><i class="fas fa-images fa-2x"></i></span>
+                                    <span v-if="status.pf_type == 'video'" class="float-right mr-3 post-icon"><i class="fas fa-video fa-2x"></i></span>
+                                    <span v-if="status.pf_type == 'video:album'" class="float-right mr-3 post-icon"><i class="fas fa-film fa-2x"></i></span>
+                                    <div class="info-overlay-text">
+                                        <h5 class="text-white m-auto font-weight-bold">
+                                            <span>
+                                                <span class="far fa-comment fa-lg p-2 d-flex-inline"></span>
+                                                <span class="d-flex-inline">{{formatCount(status.reply_count)}}</span>
+                                            </span>
+                                        </h5>
+                                    </div>
+                                </div>
+                            </a>
+                        </div>
+
+                        <div v-if="canLoadMore" class="col-12">
+                            <intersect @enter="enterIntersect">
+                                <div class="d-flex justify-content-center py-5">
+                                    <b-spinner />
+                                </div>
+                            </intersect>
+
+
+                        </div>
+                        </div>
+
+                        <div v-if="feedLoaded && !feed.length" class="row mx-0 hashtag-feed justify-content-center">
+                            <div class="col-12 col-md-8 text-center">
+                                <img src="/img/illustrations/dk-nature-man-monochrome.svg" class="img-fluid" style="opacity: 0.6;max-width:400px">
+                                <p class="lead text-muted font-weight-bold">{{ $t('hashtags.emptyFeed') }}</p>
+                            </div>
+                        </div>
+                    </template>
+
+                    <template v-else>
+                        <div class="row justify-content-center align-items-center pt-5 mt-5">
+                            <b-spinner />
+                        </div>
+                    </template>
+                </div>
+            </div>
+
+            <drawer />
+        </div>
+    </div>
 </template>
 
 <script type="text/javascript">
-	import Drawer from './partials/drawer.vue';
-	import Intersect from 'vue-intersect'
-	import Sidebar from './partials/sidebar.vue';
-	import Rightbar from './partials/rightbar.vue';
-
-	export default {
-		props: {
-			id: {
-				type: String
-			}
-		},
-
-		components: {
-			"drawer": Drawer,
-			"intersect": Intersect,
+    import Drawer from './partials/drawer.vue';
+    import Intersect from 'vue-intersect'
+    import Sidebar from './partials/sidebar.vue';
+    import Rightbar from './partials/rightbar.vue';
+
+    export default {
+        props: {
+            id: {
+                type: String
+            }
+        },
+
+        components: {
+            "drawer": Drawer,
+            "intersect": Intersect,
             "sidebar": Sidebar,
             "rightbar": Rightbar,
         },
 
         data() {
-        	return {
-        		isLoaded: false,
-        		profile: undefined,
-        		canLoadMore: false,
-        		isIntersecting: false,
-        		feedLoaded: false,
-        		feed: [],
-        		page: 1,
-        		hashtag: {
-        			name: this.id,
-        			count: 0
-        		},
-        		followingLoading: false,
-        		maxId: undefined,
-        	};
+            return {
+                isLoaded: false,
+                profile: undefined,
+                canLoadMore: false,
+                isIntersecting: false,
+                feedLoaded: false,
+                feed: [],
+                page: 1,
+                hashtag: {
+                    name: this.id,
+                    count: 0
+                },
+                followingLoading: false,
+                maxId: undefined,
+            };
+        },
+
+        mounted() {
+            this.init();
         },
 
-		mounted() {
-			this.init();
-		},
-
-		watch: {
-			'$route': 'init'
-		},
-
-		methods: {
-			init() {
-				this.profile = window._sharedData.user;
-				axios.get('/api/v1/tags/' + this.id, {
-					params: {
-						'_pe': 1
-					}
-				})
-				.then(res => {
-					this.hashtag = res.data;
-				})
-				.catch(err => {
-					swal('Error', 'Something went wrong, please try again later!', 'error');
-					this.isLoaded = true;
-					this.feedLoaded = true;
-				})
-				.finally(() => {
-					this.fetchFeed();
-				})
-			},
-
-			fetchFeed() {
-				axios.get('/api/v1/timelines/tag/' + this.id, {
-					params: {
-						limit: 80,
-					}
-				})
-				.then(res => {
-					if(res.data && res.data.length) {
-						this.feed = res.data;
-						this.maxId = res.data[res.data.length - 1].id;
-					    this.canLoadMore = true;
-					} else {
-						this.feedLoaded = true;
-						this.isLoaded = true;
-					}
-				})
-				.finally(() => {
-					this.feedLoaded = true;
-					this.isLoaded = true;
-				})
-			},
-
-			statusUrl(status) {
-				return '/i/web/post/' + status.id;
-			},
-
-			formatCount(val) {
-				return App.util.format.count(val);
-			},
-
-			enterIntersect() {
-				if(this.isIntersecting) {
-					return;
-				}
-
-				this.isIntersecting = true;
-				axios.get('/api/v1/timelines/tag/' + this.id, {
-					params: {
-						max_id: this.maxId,
-						limit: 40,
-					}
-				})
-				.then(res => {
-					if(res.data && res.data.length) {
-						this.feed.push(...res.data);
-						this.maxId = res.data[res.data.length - 1].id;
+        watch: {
+            '$route': 'init'
+        },
+
+        methods: {
+            init() {
+                this.profile = window._sharedData.user;
+                axios.get('/api/v1/tags/' + this.id, {
+                    params: {
+                        '_pe': 1
+                    }
+                })
+                .then(res => {
+                    this.hashtag = res.data;
+                })
+                .catch(err => {
+                    swal('Error', 'Something went wrong, please try again later!', 'error');
+                    this.isLoaded = true;
+                    this.feedLoaded = true;
+                })
+                .finally(() => {
+                    this.fetchFeed();
+                })
+            },
+
+            fetchFeed() {
+                axios.get('/api/v1/timelines/tag/' + this.id, {
+                    params: {
+                        limit: 80,
+                    }
+                })
+                .then(res => {
+                    if(res.data && res.data.length) {
+                        this.feed = res.data;
+                        this.maxId = res.data[res.data.length - 1].id;
                         this.canLoadMore = true;
-					} else {
+                    } else {
+                        this.feedLoaded = true;
+                        this.isLoaded = true;
+                    }
+                })
+                .finally(() => {
+                    this.feedLoaded = true;
+                    this.isLoaded = true;
+                })
+            },
+
+            statusUrl(status) {
+                return '/i/web/post/' + status.id;
+            },
+
+            formatCount(val) {
+                return App.util.format.count(val);
+            },
+
+            enterIntersect() {
+                if(this.isIntersecting) {
+                    return;
+                }
+
+                this.isIntersecting = true;
+                axios.get('/api/v1/timelines/tag/' + this.id, {
+                    params: {
+                        max_id: this.maxId,
+                        limit: 40,
+                    }
+                })
+                .then(res => {
+                    if(res.data && res.data.length) {
+                        this.feed.push(...res.data);
+                        this.maxId = res.data[res.data.length - 1].id;
+                        this.canLoadMore = true;
+                    } else {
                         this.canLoadMore = false;
-					}
-				})
-				.finally(() => {
-					this.isIntersecting = false;
-				})
-			},
-
-			goToPost(status) {
-				this.$router.push({
-					name: 'post',
-					path: `/i/web/post/${status.id}`,
-					params: {
-						id: status.id,
-						cachedStatus: status,
-						cachedProfile: this.profile
-					}
-				})
-			},
-
-			followHashtag() {
-				this.followingLoading = true;
-				axios.post('/api/v1/tags/' + this.id + '/follow')
-				.then(res => {
-					setTimeout(() => {
-						this.hashtag.following = true;
-						this.followingLoading = false;
-					}, 500);
-				});
-			},
-
-			unfollowHashtag() {
-				this.followingLoading = true;
-				axios.post('/api/v1/tags/' + this.id + '/unfollow')
-				.then(res => {
-					setTimeout(() => {
-						this.hashtag.following = false;
-						this.followingLoading = false;
-					}, 500);
-				});
-			},
-		}
-	}
+                    }
+                })
+                .finally(() => {
+                    this.isIntersecting = false;
+                })
+            },
+
+            goToPost(status) {
+                this.$router.push({
+                    name: 'post',
+                    path: `/i/web/post/${status.id}`,
+                    params: {
+                        id: status.id,
+                        cachedStatus: status,
+                        cachedProfile: this.profile
+                    }
+                })
+            },
+
+            followHashtag() {
+                this.followingLoading = true;
+                axios.post('/api/v1/tags/' + this.id + '/follow')
+                .then(res => {
+                    setTimeout(() => {
+                        this.hashtag.following = true;
+                        this.followingLoading = false;
+                    }, 500);
+                });
+            },
+
+            unfollowHashtag() {
+                this.followingLoading = true;
+                axios.post('/api/v1/tags/' + this.id + '/unfollow')
+                .then(res => {
+                    setTimeout(() => {
+                        this.hashtag.following = false;
+                        this.followingLoading = false;
+                    }, 500);
+                });
+            },
+
+            getMediaSource(status) {
+                let media = status.media_attachments[0];
+
+                if(media.preview_url && media.preview_url.endsWith('storage/no-preview.png')) {
+                    return media.url;
+                }
+
+                if(media.preview_url && media.preview_url.length) {
+                    return media.url;
+                }
+
+                return media.url;
+            }
+        }
+    }
 </script>
 
 <style lang="scss">
-	.hashtag-component {
-		.hashtag-feed {
-			.card,
-			.info-overlay-text,
-			.info-overlay-text-label,
-			img,
-			canvas {
-				border-radius: 18px !important;
-			}
-		}
-
-		.hashtag-follow {
-			width: 200px;
-		}
-
-		.ph-wrapper {
-			padding: 0.25rem;
-
-			.ph-item {
-				margin: 0;
-				padding: 0;
-				border: none;
-				background-color: transparent;
-
-				.ph-picture {
-					height: auto;
-					padding-bottom: 100%;
-					border-radius: 18px;
-				}
-
-				& > * {
-					margin-bottom: 0;
-				}
-			}
-		}
-	}
+.hashtag-component {
+    .hashtag-feed {
+        .card,
+        .info-overlay-text,
+        .info-overlay-text-label,
+        img,
+        canvas {
+            border-radius: 18px !important;
+        }
+    }
+
+    .hashtag-follow {
+        width: 200px;
+    }
+
+    .ph-wrapper {
+        padding: 0.25rem;
+
+        .ph-item {
+            margin: 0;
+            padding: 0;
+            border: none;
+            background-color: transparent;
+
+            .ph-picture {
+                height: auto;
+                padding-bottom: 100%;
+                border-radius: 18px;
+            }
+
+            & > * {
+                margin-bottom: 0;
+            }
+        }
+    }
+}
 </style>

+ 189 - 0
resources/lang/de/settings.php

@@ -0,0 +1,189 @@
+<?php
+
+return [
+    'account' =>                'Konto',
+    'accessibility' =>          'Barrierefreiheit',
+    'email' =>                  'E-Mail',
+    'invites' =>                'Einladungen',
+    'media' =>                  'Medien',
+    'notifications' =>          'Benachrichtigungen',
+    'password' =>               'Passwort',
+    'privacy' =>                'Privatsphäre',
+    'relationships' =>          'Beziehungen',
+    'security' =>               'Sicherheit',
+    'timelines' =>              'Zeitleisten',
+    'applications' =>           'Anwendungen',
+    'developers' =>             'Entwicklung',
+    'import' =>                 'Import',
+    'export' =>                 'Export',
+    'labs' =>                   'Labs',
+    'parental_controls' =>      'Elterliche Kontrolle',
+    
+    'submit' =>                 'Absenden',
+    'error' =>                  'Fehler',
+    'cancel' =>                 'Abbrechen',
+    'save' =>                   'Speichern',
+    'download' =>               'Herunterladen',
+    
+    'home.account_settings' =>                                          'Konto-Einstellungen',
+    'home.change_profile_photo' =>                                      'Profilfoto ändern',
+    'home.select_a_profile_photo' =>                                    'Wähle dein Profilfoto',
+    'home.must_be_a_jpeg_or_png_max_avatar_size' =>                     'Muss jpeg oder png sein. Maximale Größe:',
+    'home.upload' =>                                                    'Hochladen',
+    'home.delete_profile_photo' =>                                      'Profilfoto löschen',
+    'home.name' =>                                                      'Name',
+    'home.your_name' =>                                                 'Dein Name',
+    'home.website' =>                                                   'Website',
+    'home.bio' =>                                                       'Bio',
+    'home.add_a_bio_here' =>                                            'Deine Biografie',
+    'home.language' =>                                                  'Sprache',
+    'home.pronouns' =>                                                  'Pronomen',
+    'home.select_pronouns' =>                                           'Wähle Pronomen',
+    'home.select_up_to_4_pronouns_that_will_appear_on_etc' =>           'Wähle bis zu 4 Pronomen, die auf deinem Profil angezeigt werden.',
+    'home.account_aliases' =>                                           'Konto-Alias',
+    'home.manage_account_alias' =>                                      'Verwalte dein Aliaskonto',
+    'home.to_move_from_another_account_to_this_one_first_etc' =>        'Um von einem anderen Konto hierher zu migrieren, musst du zuerst einen Alias anlegen',
+    'home.account_migrate' =>                                           'Konto-Migration',
+    'home.migrate_to_another_account' =>                                'Ziehe dein Konto um',
+    'home.to_redirect_this_account_to_a_different_one_etc' =>           'Um dieses Konto auf ein anderes umzuleiten (wo es unterstützt wird).',
+    'home.storage_usage' =>                                             'Speichernutzung',
+    'home.storage_used' =>                                              'Belegter Speicher',
+    'home.are_you_sure_you_want_to_delete_your_profile_photo' =>        'Bist du sicher, dass du dein Profilfoto löschen möchtest?',
+    'home.an_error_occured_please_try_again_later' =>                   'Es ist ein Fehler aufgetreten, versuche es bitte später noch einmal',
+    
+    'accessibility.reduce_motion' =>                                    'Bewegung verringern',
+    'accessibility.prevent_animation_effects' =>                        'Animationseffekte verhindern.',
+    'accessibility.high_contrast_mode' =>                               'Hochkontrastmodus',
+    'accessibility.high_contrast_mode_for_the_visually_impaired' =>     'Hoher Kontrast für bessere Sichtbarkeit',
+    'accessibility.disable_video_autoplay' =>                           'Automatisches Abspielen deaktivieren',
+    'accessibility.prevent_videos_from_autoplaying' =>                  'Verhindert, dass Videos automatisch abgespielt werden.',
+    
+    'email.email_settings' =>                                           'Email-Einstellungen',
+    'email.email_address' =>                                            'Email-Adresse',
+    'email.verified' =>                                                 'Verifiziert',
+    'email.unverified' =>                                               'Unverifiziert',
+    'email.you_need_to' =>                                              'Du musst',
+    'email.verify_your_email' =>                                        'deine E-Mail verifizieren',
+    
+    'media.default_license' =>                                          'Standardlizenz',
+    'media.set_a_default_license_for_new_posts' =>                      'Lege eine Standardlizenz für neue Beiträge fest.',
+    'media.sync_licenses' =>                                            'Lizenzen synchronisieren',
+    'media.update_existing_posts_with_your_new_default_etc' =>          'Existierende Beiträge auf die neue Standardlizenz aktualisieren. Du kannst zweimal alle 24 Stunden synchronisieren.',
+    'media.license_changes_may_not_be_reflected_on_remote_servers' =>   'Lizenzänderungen werden unter Umständen nicht von anderen Server übernommen.',
+    'media.require_media_descriptions' =>                               'Medienbeschreibungen erzwingen',
+    'media.briefly_describe_your_media_to_improve_etc' =>               'Beschreibe deine Medien für die Verwendung mit Screenreadern (z.B. für sehbehinderte Menschen)',
+    'media.not_available_for_mobile_or_3rd_party_apps_etc' =>           'Derzeit nicht berücksichtigt in mobilen Apps und Apps von Dritten.',
+    
+    'password.update_password' =>                                       'Passwort aktualisieren',
+    'password.current' =>                                               'Aktuell',
+    'password.your_current_password' =>                                 'Dein derzeitiges Passwort',
+    'password.new' =>                                                   'Neu',
+    'password.enter_new_password_here' =>                               'Gib hier dein neues Passwort ein',
+    'password.confirm' =>                                               'Bestätigung',
+    'password.confirm_new_password' =>                                  'Bestätige dein neues Passwort hier',
+    
+    'privacy.privacy_settings' =>                                       'Privatsphäre-Einstellungen',
+    'privacy.private_account' =>                                        'Privates Konto',
+    'privacy.when_your_account_is_private_only_people_you_etc' =>       'Wenn dein Konto privat ist, können nur Leute die du genehmigt hast deine Fotos und Videos auf Pixelfed sehen. Deine bestehenden Follower sind nicht betroffen.',
+    'privacy.disable_search_engine_indexing' =>                         'Suchmaschinen-Indexierung deaktivieren',
+    'privacy.when_your_account_is_visible_to_search_engines_etc' =>     'Wenn dein Konto für Suchmaschinen sichtbar ist, können deine Informationen von Suchmaschinen besucht und gespeichert werden.',
+    'privacy.not_available_when_your_account_is_private' =>             'Nicht verfügbar bei privaten Konten',
+    'privacy.include_public_posts_in_search_results' =>                 'Öffentliche Beiträge in Suchergebnisse aufnehmen',
+    'privacy.your_public_posts_may_appear_in_search_results_etc' =>     'Deine öffentlichen Beiträge können in den Suchergebnissen auf Pixelfed und Mastodon auftauchen. Unabhängig davon können Leute, die mit deinen Beiträgen interagiert haben, sie auf jeden Fall per Suche finden.',
+    'privacy.show_on_directory' =>                                      'Im Verzeichnis anzeigen',
+    'privacy.when_this_option_is_enabled_your_profile_is_etc' =>        'Wenn diese Option aktiv ist, wird dein Profil im Verzeichnis angezeigt. Nur öffentlichen Profile kommen dafür in Frage.',
+    'privacy.receive_direct_messages_from_anyone' =>                    'Direktnachrichten von allen empfangen',
+    'privacy.if_selected_you_will_be_able_to_receive_messages_etc' =>   'Wenn diese Option aktiv ist, kannst du Direktnachrichten von allen empfangen, auch von Leuten, denen du nicht folgst.',
+    'privacy.hide_sensitive_content_from_search_results' =>             'Sensible Inhalte in Suchergebnissen ausblenden',
+    'privacy.this_prevents_posts_with_potentially_sensitive_etc' =>     'Dies verhindert, dass Beiträge mit möglicherweise sensiblem Inhalt in deinen Suchergebnissen angezeigt werden.',
+    'privacy.remove_blocked_and_muted_accounts' =>                      'Entferne geblockte und stummgeschaltete Konten',
+    'privacy.use_this_to_eliminate_search_results_from_accounts_etc' => 'Aktiviere, um Suchergebnisse von Konten, die du geblockt oder stummgeschaltet hast, zu entferen.',
+    'privacy.display_media_that_may_contain_sensitive_content' =>       'Medien mit sensiblen Inhalten anzeigen',
+    'privacy.show_all_media_including_potentially_sensitive_content' => 'Alle Medien anzeigen, inklusive sensibler Inhalte.',
+    'privacy.show_follower_count' =>                                    'Anzahl von Followern anzeigen',
+    'privacy.display_follower_count_on_profile' =>                      'Zeige die Anzahl von Followern im Profil',
+    'privacy.show_following_count' =>                                   'Anzahl Folgender anzeigen',
+    'privacy.display_following_count_on_profile' =>                     'Zeige die Anzahl von Folgenden im Profil',
+    'privacy.disable_embeds' =>                                         'Einbettung deaktivieren',
+    'privacy.disable_post_and_profile_embeds' =>                        'Deaktiviere die Einbettung von Beiträgen und Profilen',
+    'privacy.enable_atom_feed' =>                                       'Atom-Feed aktivieren',
+    'privacy.enable_your_profile_atom_feed_only_public_profiles_etc' => 'Aktiviere deinen Atom-Feed. Nur öffentliche Profile kommen dafür in Frage',
+    'privacy.confirm_this_action' =>                                    'Diese Aktion bestätigen',
+    'privacy.please_select_the_type_of_private_account_you_etc' =>      'Bitte wähle die Art von privatem Account, die du möchtest:',
+    'privacy.keep_existing_followers' =>                                'Alle bestehende Follower behalten',
+    'privacy.only_keep_mutual_followers' =>                             'Nur gegenseitige Follower behalten',
+    'privacy.only_followers_that_have_followed_you_for_atleast' =>      'Nur Follower behalten, die dir folgen seit wenigstens',
+    'privacy.hour' =>                                                   'Stunde',
+    'privacy.day' =>                                                    'Tag',
+    'privacy.weeks' =>                                                  'Wochen',
+    'privacy.month' =>                                                  'Monat',
+    'privacy.months' =>                                                 'Monate',
+    'privacy.year' =>                                                   'Jahr',
+    'privacy.remove_existing_followers' =>                              'Alle Follower entfernen',
+    'privacy.allow_new_follow_requests' =>                              'Ermögliche neue Folgeanfragen',
+    'privacy.block_notifications_from_accounts_i_dont_follow' =>        'Blockiere Benachrichtigungen von Konten, denen ich nicht folge',
+    'privacy.an_error_occured_please_try_again' =>                      'Es ist ein Fehler aufgetreten, versuche es bitte noch einmal',
+    
+    'relationships' =>                                                          'Beziehungen',
+    'relationships.followers' =>                                                'Follower',
+    'relationships.following' =>                                                'Folge ich',
+    'relationships.hashtags' =>                                                 'Hashtags',
+    'relationships.hashtag' =>                                                  'Hashtag',
+    'relationships.username' =>                                                 'Benutzername',
+    'relationships.action' =>                                                   'Aktion',
+    'relationships.unfollow' =>                                                 'Entfolgen',
+    'relationships.mute' =>                                                     'Stummschalten',
+    'relationships.block' =>                                                    'Blockieren',
+    'relationships.mute_successful' =>                                          'Stummschalten erfolgreich',
+    'relationships.you_have_successfully_muted_that_user' =>                    'Du hast den Benutzer erfolgreich stummgeschaltet',
+    'relationships.block_successful' =>                                         'Blockieren erfolgreich',
+    'relationships.you_have_successfully_blocked_that_user' =>                  'Du hast den Benutzer erfolgreich geblockt',
+    'relationships.unfollow_successful' =>                                      'Entfolgen erfolgreich',
+    'relationships.you_have_successfully_unfollowed_that_user' =>               'Du hast den Benutzer erfolgreich entfolgt',
+    'relationships.an_error_occured_when_attempting_to_unfollow_this_user' =>   'Beim Versuch den Benutzer zu entfolgen ist ein Fehler aufgetreten',
+    'relationships.you_have_successfully_unfollowed_that_hashtag' =>            'Du hast den Hashtag erfolgreich entfolgt',
+    
+    'security.two_factor_authentication' =>                                     'Zwei-Faktor-Authentifizierung',
+    'security.enabled' =>                                                       'Aktiviert',
+    'security.danger_zone' =>                                                   'Gefahrenbereich',
+    'security.temporarily_disable_account' =>                                   'Konto temporär deaktivieren',
+    'security.disable_your_account_to_hide_your_posts_until_next_log_in' =>     'Deaktiviere dein Konto um deine Beiträge bis zu deinem nächsten Einloggen zu verstecken',
+    'security.disable' =>                                                       'Deaktiviert',
+    'security.delete_this_account' =>                                           'Dieses Konto löschen',
+    'security.once_you_delete_your_account_there_is_no_going_back_etc' =>       'Wenn dein Konto gelöscht wurde, gibt es kein zurück mehr. Bitte sei dir darin sicher.',
+    'security.delete' =>                                                        'Löschen',
+    'security.account_log' =>                                                   'Konto-Log',
+    'security.no_activity_logs_found' =>                                        'Kein Aktivitätenlog gefunden!',
+    'security.ip_address' =>                                                    'IP-Adresse:',
+    'security.user_agent' =>                                                    'User-Agent:',
+    'security.devices' =>                                                       'Geräte',
+    'security.ip' =>                                                            'IP:',
+    'security.device' =>                                                        'Gerät:',
+    'security.browser' =>                                                       'Browser:',
+    'security.last_login' =>                                                    'Letzer Login:',
+    'security.country' =>                                                       'Land:',
+    'security.trust' =>                                                         'Vertrauen',
+    'security.remove_device' =>                                                 'Gerät entfernen',
+    'security.timeline_settings' =>                                             'Zeitleisten-Einstellungen',
+	'security.show_text_only_posts' =>                                          'Nur-Text-Beiträge anzeigen',
+	'security.show_text_only_posts_from_accounts_you_follow_home_etc' =>        'Zeige Nur-Text-Beiträge von Konten, denen du folgst. (nur auf der Startseite)',
+	'security.show_replies' =>                                                  'Antworten anzeigen',
+	'security.show_replies_from_accounts_you_follow_home_timeline_only' =>      'Zeige Antworten von Konten, denen du folgst. (nur auf der Startseite)',
+    'security.show_reblogs' =>                                                  'Reblogs anzeigen',
+    'security.see_reblogs_from_accounts_you_follow_in_your_home_etc' =>         'Zeige Reblogs von Konten, denen du folgst. (nur auf der Startseite)',
+    'security.photo_reblogs_only' =>                                            'Ausschließlich Foto-Reblogs',
+    'security.only_see_reblogs_of_photos_or_photo_albums_home_etc' =>           'Nur Reblogs von Fotos oder Foto-Alben anzeigen. (nur auf der Startseite)',
+    
+    'developers.oauth_has_not_been_enabled_on_this_instance' =>                 'OAuth ist auf dieser Instanz nicht aktiv.',
+    
+    'import.import_from_instagram' =>                                           'Importieren von Instagram',
+    
+    'export.data_export' =>                                                     'Daten-Export',
+    'export.we_generate_data_exports_once_per_hour_and_they_may_etc' =>         'Datenexporte werden stündlich erzeugt und enthalten möglicherweise nicht die neusten Daten, wenn du vor kurzem bereits einmal einen Export angefordert hast.',
+    'export.statuses' =>                                                        'Beiträge',
+    'export.mute_block_lists' =>                                                'Stumm/Block-Listen',
+    
+    'labs' =>                                                                   'Labs',
+	'labs.experimental_features' =>                                             'Experimentelle Funktionen',
+    'labs.use_dark_mode_theme' =>                                               'Das Dark Mode-Theme verwenden.',
+];

+ 39 - 1
resources/lang/de/site.php

@@ -28,4 +28,42 @@ return [
     'Submit'                                                => 'Absenden',
     'log_in_to_send_a_message'                              => 'melde dich an, um eine Nachricht zu senden',
     'Please'                                                => 'Bitte',
-];
+    
+    // site/about
+    'photo_sharing_for_everyone'                            => 'Fotos teilen. Für Alle',
+    'pixelfed_is_an_image_sharing_platform_etc'             => 'Pixelfed ist eine Plattform zum Teilen von Bildern. Eine ethische Alternative zu zentralisierten Plattformen', // this is actually never used because it's a fallback for config_cache('app.description') and config_cache('app.short_description') which seem to be impossible to set to empty when saved via /admin/settings?t=branding
+    'feature_packed'                                        => 'Voller Funktionen.',
+    'the_best_for_the_brightest'                            => 'Das Beste für die schönsten 📸',
+    'albums'                                                => 'Alben',
+    'share_posts_with_up_to'                                => 'Teile Beiträge mit bis zu',
+    'photos'                                                => 'Fotos',
+    'comments'                                              => 'Kommentare',
+    'comment_on_a_post_or_send_a_reply'                     => 'Kommentiere und beantworte Beiträge',
+    'collections'                                           => 'Sammlungen',
+    'organize_and_share_collections_of_multiple_posts'      => 'Organisiere und teile Sammlungen von mehreren Beiträgen',
+    'discover'                                              => 'Entdecken',
+    'explore_categories_hashtags_and_topics'                => 'Erkunde Kategorien, Hashtags und Themen',
+    'photo_filters'                                         => 'Foto-Filter',
+    'add_a_special_touch_to_your_photos'                    => 'Verleih deinen Fotos das gewisse Etwas',
+    'stories'                                               => 'Stories',
+    'share_moments_with_your_followers_that_disappear_etc'  => 'Teile Momente mit deinen Followern für 24 Stunden',
+    'people_have_shared'                                    => 'Leute haben',
+    'photos_and_videos_on'                                  => 'Fotos und Videos geteilt auf',
+    'sign_up_today'                                         => 'Melde dich jetzt an',
+    'and_join_our_community_of_photographers_from_etc'      => 'und werde Teil unserer Community von Fotograf*innen auf der ganzen Welt.',
+
+    //site/fediverse
+    'is_a_portmanteau_of_federation_and_universe_etc'       => 'ist ein Kofferwort aus “federation” (Föderation) und “universe” (Universum). Es ist ein gebräuchlicher, unverbindlicher Name für einen Zusammenschluss von Servern sozialer Netzwerke, die auf verschiedene Arten von Medien spezialisiert sind.',
+    'supported_fediverse_projects'                          => 'Unterstützte Fediverse-Projekte',
+    'some_of_the_better_known_fediverse_projects_include'   => 'Einige der bekanntesten Fediverse-Projekte sind:',
+    'a_federated_microblogging_alternative'                 => 'Eine föderierte Mikroblogging-Alternative',
+
+    // site/opensource
+    'the_software_that_powers_this_website_is_called'       => 'Die Software, mit der diese Website läuft, heißt',
+    'and_anyone_can'                                        => 'und jede*r kann sie',
+    'download'                                              => 'herunter laden',
+    'opensource.or'                                         => 'oder ihren Quellcode',
+    'view'                                                  => 'ansehen',
+    'the_source_code_and_run_their_own_instance'            => 'und eine eigene Instanz betreiben!',
+    'open_source_in_pixelfed'                               => 'Open Source in Pixelfed',
+];

+ 9 - 0
resources/lang/de/web.php

@@ -195,6 +195,15 @@ return [
 	'hashtags' => [
 		'emptyFeed' => 'Wir können keine Beiträge mit diesem Hashtag finden'
 	],
+	
+	'report' => [
+		'report' => 'Melden',
+		'selectReason' => 'Wähle einen Grund',
+		'reported' => 'Gemeldet',
+		'sendingReport' => 'Sende Meldung',
+		'thanksMsg' => 'Danke für deine Meldung! Damit erhöhst du die Sicherheit der Community!',
+		'contactAdminMsg' => 'Wenn du die Administration wegen diesem Beitrag oder dieser Meldung kontaktieren möchtest',
+	],
 
 	'report' => [
 		'report' => 'Melden',

+ 195 - 0
resources/lang/en/settings.php

@@ -0,0 +1,195 @@
+<?php
+
+return [
+    'account' =>                'Account',
+    'accessibility' =>          'Accessibility',
+    'email' =>                  'Email',
+    'invites' =>                'Invites',
+    'media' =>                  'Media',
+    'notifications' =>          'Notifications',
+    'password' =>               'Password',
+    'privacy' =>                'Privacy',
+    'relationships' =>          'Relationships',
+    'security' =>               'Security',
+    'timelines' =>              'Timelines',
+    'applications' =>           'Applications',
+    'developers' =>             'Developers',
+    'import' =>                 'Import',
+    'export' =>                 'Export',
+    'labs' =>                   'Labs',
+    'parental_controls' =>      'Parental Controls',
+  
+    'submit' =>                 'Submit',
+    'error' =>                  'Error',
+    'cancel' =>                 'Cancel',
+    'save' =>                   'Save',
+    'download' =>               'Download',
+    
+    'home.account_settings' =>                                          'Account Settings',
+    'home.change_profile_photo' =>                                      'Change Profile Photo',
+    'home.select_a_profile_photo' =>                                    'Select a profile photo',
+    'home.must_be_a_jpeg_or_png_max_avatar_size' =>                     'Must be a jpeg or png. Max avatar size:',
+    'home.upload' =>                                                    'Upload',
+    'home.delete_profile_photo' =>                                      'Delete Profile Photo',
+    'home.name' =>                                                      'Name',
+    'home.your_name' =>                                                 'Your Name',
+    'home.website' =>                                                   'Website',
+    'home.bio' =>                                                       'Bio',
+    'home.add_a_bio_here' =>                                            'Add a bio here',
+    'home.language' =>                                                  'Language',
+    'home.pronouns' =>                                                  'Pronouns',
+    'home.select_pronouns' =>                                           'Select Pronoun(s)',
+    'home.select_up_to_4_pronouns_that_will_appear_on_etc' =>           'Select up to 4 pronouns that will appear on your profile.',
+    'home.account_aliases' =>                                           'Account Aliases',
+    'home.manage_account_alias' =>                                      'Manage account alias',
+    'home.to_move_from_another_account_to_this_one_first_etc' =>        'To move from another account to this one, first you need to create an alias.',
+    'home.account_migrate' =>                                           'Account Migrate',
+    'home.migrate_to_another_account' =>                                'Migrate to another account',
+    'home.to_redirect_this_account_to_a_different_one_etc' =>           'To redirect this account to a different one (where supported).',
+    'home.storage_usage' =>                                             'Storage Usage',
+    'home.storage_used' =>                                              'Storage Used',
+    'home.are_you_sure_you_want_to_delete_your_profile_photo' =>        'Are you sure you want to delete your profile photo?',
+    'home.an_error_occured_please_try_again_later' =>                   'An error occured, please try again later',
+    
+    'accessibility.reduce_motion' =>                                    'Reduce Motion',
+    'accessibility.prevent_animation_effects' =>                        'Prevent animation effects.',
+    'accessibility.high_contrast_mode' =>                               'High Contrast Mode',
+    'accessibility.high_contrast_mode_for_the_visually_impaired' =>     'High contrast mode for the visually impaired.',
+    'accessibility.disable_video_autoplay' =>                           'Disable video autoplay',
+    'accessibility.prevent_videos_from_autoplaying' =>                  'Prevent videos from autoplaying.',
+    
+    'email.email_settings' =>                                           'Email Settings',
+    'email.email_address' =>                                            'Email Address',
+    'email.verified' =>                                                 'Verified',
+    'email.unverified' =>                                               'Unverified',
+    'email.you_need_to' =>                                              'You need to',
+    'email.verify_your_email' =>                                        'verify your email',
+    
+    'media.default_license' =>                                          'Default License',
+    'media.set_a_default_license_for_new_posts' =>                      'Set a default license for new posts.',
+    'media.sync_licenses' =>                                            'Sync Licenses',
+    'media.update_existing_posts_with_your_new_default_etc' =>          'Update existing posts with your new default license. You can sync twice every 24 hours.',
+    'media.license_changes_may_not_be_reflected_on_remote_servers' =>   'License changes may not be reflected on remote servers.',
+    'media.require_media_descriptions' =>                               'Require Media Descriptions',
+    'media.briefly_describe_your_media_to_improve_etc' =>               'Briefly describe your media to improve accessibility for vision impaired people.',
+    'media.not_available_for_mobile_or_3rd_party_apps_etc' =>           'Not available for mobile or 3rd party apps at this time.',
+    
+    'password.update_password' =>                                       'Update Password',
+    'password.current' =>                                               'Current',
+    'password.your_current_password' =>                                 'Your current password',
+    'password.new' =>                                                   'New',
+    'password.enter_new_password_here' =>                               'Enter new password here',
+    'password.confirm' =>                                               'Confirm',
+    'password.confirm_new_password' =>                                  'Confirm new password',
+    
+    'privacy.privacy_settings' =>                                       'Privacy Settings',
+    'privacy.private_account' =>                                        'Private Account',
+    'privacy.when_your_account_is_private_only_people_you_etc' =>       'When your account is private, only people you approve can see your photos and videos on pixelfed. Your existing followers won\'t be affected.',
+    'privacy.disable_search_engine_indexing' =>                         'Disable Search Engine indexing',
+    'privacy.when_your_account_is_visible_to_search_engines_etc' =>     'When your account is visible to search engines, your information can be crawled and stored by search engines.',
+    'privacy.not_available_when_your_account_is_private' =>             'Not available when your account is private',
+    'privacy.include_public_posts_in_search_results' =>                 'Include public posts in search results',
+    'privacy.your_public_posts_may_appear_in_search_results_etc' =>     'Your public posts may appear in search results on Pixelfed and Mastodon. People who have interacted with your posts may be able to search them regardless.',
+    'privacy.show_on_directory' =>                                      'Show on Directory',
+    'privacy.when_this_option_is_enabled_your_profile_is_etc' =>        'When this option is enabled, your profile is included in the Directory. Only public profiles are eligible.',
+    'privacy.receive_direct_messages_from_anyone' =>                    'Receive Direct Messages from anyone',
+    'privacy.if_selected_you_will_be_able_to_receive_messages_etc' =>   'If selected, you will be able to receive messages and notifications from any user even if you do not follow them.',
+    'privacy.hide_sensitive_content_from_search_results' =>             'Hide sensitive content from search results',
+    'privacy.this_prevents_posts_with_potentially_sensitive_etc' =>     'This prevents posts with potentially sensitive content from displaying in your search results.',
+    'privacy.remove_blocked_and_muted_accounts' =>                      'Remove blocked and muted accounts',
+    'privacy.use_this_to_eliminate_search_results_from_accounts_etc' => 'Use this to eliminate search results from accounts you\'ve blocked or muted.',
+    'privacy.display_media_that_may_contain_sensitive_content' =>       'Display media that may contain sensitive content',
+    'privacy.show_all_media_including_potentially_sensitive_content' => 'Show all media, including potentially sensitive content.',
+    'privacy.show_follower_count' =>                                    'Show Follower Count',
+    'privacy.display_follower_count_on_profile' =>                      'Display follower count on profile',
+    'privacy.show_following_count' =>                                   'Show Following Count',
+    'privacy.display_following_count_on_profile' =>                     'Display following count on profile',
+    'privacy.disable_embeds' =>                                         'Disable Embeds',
+    'privacy.disable_post_and_profile_embeds' =>                        'Disable post and profile embeds',
+    'privacy.enable_atom_feed' =>                                       'Enable Atom Feed',
+    'privacy.enable_your_profile_atom_feed_only_public_profiles_etc' => 'Enable your profile atom feed. Only public profiles are eligible.',
+    'privacy.confirm_this_action' =>                                    'Confirm this action',
+    'privacy.please_select_the_type_of_private_account_you_etc' =>      'Please select the type of private account you would like:',
+    'privacy.keep_existing_followers' =>                                'Keep existing followers',
+    'privacy.only_keep_mutual_followers' =>                             'Only keep mutual followers',
+    'privacy.only_followers_that_have_followed_you_for_atleast' =>      'Only followers that have followed you for atleast',
+    'privacy.hour' =>                                                   'hour',
+    'privacy.day' =>                                                    'day',
+    'privacy.weeks' =>                                                  'weeks',
+    'privacy.month' =>                                                  'month',
+    'privacy.months' =>                                                 'months',
+    'privacy.year' =>                                                   'year',
+    'privacy.remove_existing_followers' =>                              'Remove existing followers',
+    'privacy.allow_new_follow_requests' =>                              'Allow new follow requests',
+    'privacy.block_notifications_from_accounts_i_dont_follow' =>        'Block notifications from accounts I don\'t follow',
+    'privacy.an_error_occured_please_try_again' =>                      'An error occured. Please try again.',
+  
+    'relationships' =>                                                          'Relationships',
+    'relationships.followers' =>                                                'Followers',
+    'relationships.following' =>                                                'Following',
+    'relationships.hashtags' =>                                                 'Hashtags',
+    'relationships.hashtag' =>                                                  'Hashtag',
+    'relationships.username' =>                                                 'Username',
+    'relationships.action' =>                                                   'Action',
+    'relationships.unfollow' =>                                                 'Unfollow',
+    'relationships.mute' =>                                                     'Mute',
+    'relationships.block' =>                                                    'Block',
+    'relationships.mute_successful' =>                                          'Mute Successful',
+    'relationships.you_have_successfully_muted_that_user' =>                    'You have successfully muted that user',
+    'relationships.block_successful' =>                                         'Block Successful',
+    'relationships.you_have_successfully_blocked_that_user' =>                  'You have successfully blocked that user',
+    'relationships.unfollow_successful' =>                                      'Unfollow Successful',
+    'relationships.you_have_successfully_unfollowed_that_user' =>               'You have successfully unfollowed that user',
+    'relationships.an_error_occured_when_attempting_to_unfollow_this_user' =>   'An error occured when attempting to unfollow this user',
+    'relationships.you_have_successfully_unfollowed_that_hashtag' =>            'You have successfully unfollowed that hashtag',
+    
+    'security.two_factor_authentication' =>                                     'Two-factor authentication',
+    'security.enabled' =>                                                       'Enabled',
+    'security.danger_zone' =>                                                   'Danger Zone',
+    'security.temporarily_disable_account' =>                                   'Temporarily Disable Account',
+    'security.disable_your_account_to_hide_your_posts_until_next_log_in' =>     'Disable your account to hide your posts until next log in.',
+    'security.disable' =>                                                       'Disable',
+    'security.delete_this_account' =>                                           'Delete this Account',
+    'security.once_you_delete_your_account_there_is_no_going_back_etc' =>       'Once you delete your account, there is no going back. Please be certain.',
+    'security.delete' =>                                                        'Delete',
+    'security.account_log' =>                                                   'Account Log',
+    'security.no_activity_logs_found' =>                                        'No activity logs found!',
+    'security.ip_address' =>                                                    'IP Address:',
+    'security.user_agent' =>                                                    'User Agent:',
+    'security.devices' =>                                                       'Devices',
+    'security.ip' =>                                                            'IP:',
+    'security.device' =>                                                        'Device:',
+    'security.browser' =>                                                       'Browser:',
+    'security.last_login' =>                                                    'Last Login:',
+    'security.country' =>                                                       'Country:',
+    'security.trust' =>                                                         'Trust',
+    'security.remove_device' =>                                                 'Remove Device',
+    'security.timeline_settings' =>                                             'Timeline Settings',
+    'security.show_text_only_posts' =>                                          'Show text-only posts',
+    'security.show_text_only_posts_from_accounts_you_follow_home_etc' =>        'Show text-only posts from accounts you follow. (Home timeline only)',
+    'security.show_replies' =>                                                  'Show replies',
+    'security.show_replies_from_accounts_you_follow_home_timeline_only' =>      'Show replies from accounts you follow. (Home timeline only)',
+    'security.show_reblogs' =>                                                  'Show reblogs',
+    'security.see_reblogs_from_accounts_you_follow_in_your_home_etc' =>         'See reblogs from accounts you follow in your home feed. (Home timeline only)',
+    'security.photo_reblogs_only' =>                                            'Photo reblogs only',
+    'security.only_see_reblogs_of_photos_or_photo_albums_home_etc' =>           'Only see reblogs of photos or photo albums. (Home timeline only)',
+    
+    // incomplete
+    // the oauth panel is loaded from elsewhere 
+    'developers.oauth_has_not_been_enabled_on_this_instance' =>                 'OAuth has not been enabled on this instance.',
+    
+    // incomplete
+    // import/ig.blade.php seems not in use anymore
+    'import.import_from_instagram' =>                                           'Import from Instagram',
+    
+    'export.data_export' =>                                                     'Data Export',
+    'export.we_generate_data_exports_once_per_hour_and_they_may_etc' =>         'We generate data exports once per hour, and they may not contain the latest data if you\'ve requested them recently.',
+    'export.statuses' =>                                                        'Statuses',
+    'export.mute_block_lists' =>                                                'Mute/Block List',
+    
+    // incomplete
+    // some language outside the blades (in app/Http/Controllers/Settings/LabsSettings.php)
+    'labs' =>                                                                   'Labs',
+    'labs.experimental_features' =>                                             'Experimental features',
+    'labs.use_dark_mode_theme' =>                                               'Use dark mode theme.',
+];

+ 39 - 1
resources/lang/en/site.php

@@ -28,4 +28,42 @@ return [
     'Submit'                                                => 'Submit',
     'log_in_to_send_a_message'                              => 'log in to send a message',
     'Please'                                                => 'Please',
-];
+
+    // site/about
+    'photo_sharing_for_everyone'                            => 'Photo Sharing. For Everyone',
+    'pixelfed_is_an_image_sharing_platform_etc'             => 'Pixelfed is an image sharing platform, an ethical alternative to centralized platforms.', // this is actually never used because it's a fallback for config_cache('app.description') and config_cache('app.short_description') which seem to be impossible to set to empty when saved via /admin/settings?t=branding
+    'feature_packed'                                        => 'Feature Packed.',
+    'the_best_for_the_brightest'                            => 'The best for the brightest 📸',
+    'albums'                                                => 'Albums',
+    'share_posts_with_up_to'                                => 'Share posts with up to',
+    'photos'                                                => 'photos',
+    'comments'                                              => 'Comments',
+    'comment_on_a_post_or_send_a_reply'                     => 'Comment on a post, or send a reply',
+    'collections'                                           => 'Collections',
+    'organize_and_share_collections_of_multiple_posts'      => 'Organize and share collections of multiple posts',
+    'discover'                                              => 'Discover',
+    'explore_categories_hashtags_and_topics'                => 'Explore categories, hashtags and topics',
+    'photo_filters'                                         => 'Photo Filters',
+    'add_a_special_touch_to_your_photos'                    => 'Add a special touch to your photos',
+    'stories'                                               => 'Stories',
+    'share_moments_with_your_followers_that_disappear_etc'  => 'Share moments with your followers that disappear after 24 hours',
+    'people_have_shared'                                    => 'people have shared',
+    'photos_and_videos_on'                                  => 'photos and videos on',
+    'sign_up_today'                                         => 'Sign up today',
+    'and_join_our_community_of_photographers_from_etc'      => 'and join our community of photographers from around the world.',
+
+    // site/fediverse
+    'is_a_portmanteau_of_federation_and_universe_etc'       => 'is a portmanteau of “federation” and “universe”. It is a common, informal name for a federation of social network servers, specializing in different types of media.',
+    'supported_fediverse_projects'                          => 'Supported Fediverse Projects',
+    'some_of_the_better_known_fediverse_projects_include'   => 'Some of the better known fediverse projects include:',
+    'a_federated_microblogging_alternative'                 => 'A federated microblogging alternative.',
+
+    // site/opensource
+    'the_software_that_powers_this_website_is_called'       => 'The software that powers this website is called',
+    'and_anyone_can'                                        => 'and anyone can',
+    'download'                                              => 'download',
+    'opensource.or'                                         => 'or',
+    'view'                                                  => 'view',
+    'the_source_code_and_run_their_own_instance'            => 'the source code and run their own instance!',
+    'open_source_in_pixelfed'                               => 'Open source in Pixelfed',
+];

+ 8 - 8
resources/views/settings/accessibility.blade.php

@@ -3,7 +3,7 @@
 @section('section')
 
   <div class="title">
-    <h3 class="font-weight-bold">Accessibility</h3>
+    <h3 class="font-weight-bold">{{__('settings.accessibility')}}</h3>
   </div>
   <hr>
   <form method="post">
@@ -25,9 +25,9 @@
     <div class="form-check pb-3">
       <input class="form-check-input" type="checkbox" name="reduce_motion" id="reduce_motion" {{$settings->reduce_motion ? 'checked=""':''}}>
       <label class="form-check-label font-weight-bold" for="reduce_motion">
-        {{__('Reduce Motion')}}
+        {{__('settings.accessibility.reduce_motion')}}
       </label>
-      <p class="text-muted small help-text">Prevent animation effects.</p>
+      <p class="text-muted small help-text">{{__('settings.accessibility.prevent_animation_effects')}}</p>
     </div>
     {{-- <div class="form-check pb-3">
       <input class="form-check-input" type="checkbox" name="optimize_screen_reader" id="optimize_screen_reader" {{$settings->optimize_screen_reader ? 'checked=""':''}}>
@@ -39,21 +39,21 @@
     <div class="form-check pb-3">
       <input class="form-check-input" type="checkbox" name="high_contrast_mode" id="high_contrast_mode" {{$settings->high_contrast_mode ? 'checked=""':''}}>
       <label class="form-check-label font-weight-bold" for="high_contrast_mode">
-        {{__('High Contrast Mode')}}
+        {{__('settings.accessibility.high_contrast_mode')}}
       </label>
-      <p class="text-muted small help-text">High contrast mode for the visually impaired.</p>
+      <p class="text-muted small help-text">{{__('settings.accessibility.high_contrast_mode_for_the_visually_impaired')}}</p>
     </div>
     <div class="form-check pb-3">
       <input class="form-check-input" type="checkbox" name="video_autoplay" id="video_autoplay" {{$settings->video_autoplay ? 'checked=""':''}}>
       <label class="form-check-label font-weight-bold" for="video_autoplay">
-        {{__('Disable video autoplay')}}
+        {{__('settings.accessibility.disable_video_autoplay')}}
       </label>
-      <p class="text-muted small help-text">Prevent videos from autoplaying.</p>
+      <p class="text-muted small help-text">{{__('settings.accessibility.prevent_videos_from_autoplaying')}}</p>
     </div>
     <div class="form-group row mt-5 pt-5">
       <div class="col-12 text-right">
         <hr>
-        <button type="submit" class="btn btn-primary font-weight-bold py-0 px-5">Submit</button>
+        <button type="submit" class="btn btn-primary font-weight-bold py-0 px-5">{{__('settings.submit')}}</button>
       </div>
     </div>
   </form>

+ 12 - 12
resources/views/settings/dataexport.blade.php

@@ -3,42 +3,42 @@
 @section('section')
 
   <div class="title">
-    <h3 class="font-weight-bold">Data Export</h3>
+    <h3 class="font-weight-bold">{{__('settings.export.data_export')}}</h3>
   </div>
   <hr>
-  <div class="alert alert-primary px-3 h6">We generate data exports once per hour, and they may not contain the latest data if you've requested them recently.</div>
+  <div class="alert alert-primary px-3 h6">{{__('settings.export.we_generate_data_exports_once_per_hour_and_they_may_etc')}}</div>
   <ul class="list-group">
   	<li class="list-group-item d-flex justify-content-between align-items-center">
   		<div>
-  			<span class="font-weight-bold">Following</span>
+  			<span class="font-weight-bold">{{__('settings.relationships.following')}}</span>
   		</div>
   		<div>
         <form action="/settings/data-export/following" method="post">
           @csrf
-          <button type="submit" class="font-weight-bold btn btn-outline-primary btn-sm">Download</button>
+          <button type="submit" class="font-weight-bold btn btn-outline-primary btn-sm">{{__('settings.download')}}</button>
         </form>
   		</div>
   	</li>
  	<li class="list-group-item d-flex justify-content-between align-items-center">
   		<div>
-  			<span class="font-weight-bold">Followers</span>
+  			<span class="font-weight-bold">{{__('settings.relationships.followers')}}</span>
   		</div>
       <div>
         <form action="/settings/data-export/followers" method="post">
           @csrf
-          <button type="submit" class="font-weight-bold btn btn-outline-primary btn-sm">Download</button>
+          <button type="submit" class="font-weight-bold btn btn-outline-primary btn-sm">{{__('settings.download')}}</button>
         </form>
       </div>
   	</li>
  	<li class="list-group-item d-flex justify-content-between align-items-center">
   		<div>
-  			<span class="font-weight-bold">Statuses</span>
+  			<span class="font-weight-bold">{{__('settings.export.statuses')}}</span>
   		</div>
   		<div>
         <form action="/settings/data-export/statuses" method="post" class="d-inline">
           @csrf
           <input type="hidden" name="type" value="ap">
-          <button type="submit" class="font-weight-bold btn btn-outline-primary btn-sm">Download</button>
+          <button type="submit" class="font-weight-bold btn btn-outline-primary btn-sm">{{__('settings.download')}}</button>
         </form>
         {{-- <form action="/settings/data-export/statuses" method="post" class="d-inline">
           @csrf
@@ -49,23 +49,23 @@
     </li>
   <li class="list-group-item d-flex justify-content-between align-items-center">
       <div>
-        <span class="font-weight-bold">Mute/Block List</span>
+        <span class="font-weight-bold">{{__('settings.export.mute_block_lists')}}</span>
       </div>
       <div>
         <form action="/settings/data-export/mute-block-list" method="post">
           @csrf
-          <button type="submit" class="font-weight-bold btn btn-outline-primary btn-sm">Download</button>
+          <button type="submit" class="font-weight-bold btn btn-outline-primary btn-sm">{{__('settings.download')}}</button>
         </form>
       </div>
     </li>
   <li class="list-group-item d-flex justify-content-between align-items-center">
       <div>
-        <span class="font-weight-bold">Account</span>
+        <span class="font-weight-bold">{{__('settings.account')}}</span>
       </div>
       <div>
   			<form action="/settings/data-export/account" method="post">
           @csrf
-          <button type="submit" class="font-weight-bold btn btn-outline-primary btn-sm">Download</button>
+          <button type="submit" class="font-weight-bold btn btn-outline-primary btn-sm">{{__('settings.download')}}</button>
         </form>
   		</div>
   	</li>

+ 2 - 2
resources/views/settings/developers.blade.php

@@ -3,13 +3,13 @@
 @section('section')
 
 <div class="title">
-	<h3 class="font-weight-bold">Developers</h3>
+	<h3 class="font-weight-bold">{{__('settings.developers')}}</h3>
 </div>
 <hr>
 @if((bool) config_cache('pixelfed.oauth_enabled') == true)
 	<passport-clients></passport-clients>
 @else
-	<p class="lead">OAuth has not been enabled on this instance.</p>
+	<p class="lead">{{__('settings.developers.oauth_has_not_been_enabled_on_this_instance')}}</p>
 @endif
 
 @endsection

+ 5 - 5
resources/views/settings/email.blade.php

@@ -5,7 +5,7 @@
 <div class="d-flex justify-content-between align-items-center">
     <div class="title d-flex align-items-center" style="gap: 1rem;">
         <p class="mb-0"><a href="/settings/home"><i class="far fa-chevron-left fa-lg"></i></a></p>
-        <h3 class="font-weight-bold mb-0">Email Settings</h3>
+        <h3 class="font-weight-bold mb-0">{{__('settings.email.email_settings')}}</h3>
     </div>
 </div>
 
@@ -17,19 +17,19 @@
     <input type="hidden" class="form-control" name="website" value="{{Auth::user()->profile->website}}">
 
     <div class="form-group">
-        <label for="email" class="font-weight-bold">Email Address</label>
+        <label for="email" class="font-weight-bold">{{__('settings.email.email_address')}}</label>
         <input type="email" class="form-control" id="email" name="email" placeholder="Email Address" value="{{Auth::user()->email}}">
         <p class="help-text small text-muted font-weight-bold">
             @if(Auth::user()->email_verified_at)
-            <span class="text-success">Verified</span> {{Auth::user()->email_verified_at->diffForHumans()}}
+            <span class="text-success">{{__('settings.email.verified')}}</span> {{Auth::user()->email_verified_at->diffForHumans()}}
             @else
-            <span class="text-danger">Unverified</span> You need to <a href="/i/verify-email">verify your email</a>.
+            <span class="text-danger">{{__('settings.email.unverified')}}</span> {{__('settings.email.you_need_to')}} <a href="/i/verify-email">{{__('settings.email.verify_your_email')}}</a>.
             @endif
         </p>
     </div>
     <div class="form-group row">
         <div class="col-12 text-right">
-            <button type="submit" class="btn btn-primary font-weight-bold py-0 px-5">Submit</button>
+            <button type="submit" class="btn btn-primary font-weight-bold py-0 px-5">{{__('settings.submit')}}</button>
         </div>
     </div>
 </form>

+ 27 - 27
resources/views/settings/home.blade.php

@@ -3,7 +3,7 @@
 @section('section')
 
 	<div class="title">
-		<h3 class="font-weight-bold">Account Settings</h3>
+		<h3 class="font-weight-bold">{{__('settings.home.account_settings')}}</h3>
 	</div>
 	<hr>
 	<div class="form-group row">
@@ -13,7 +13,7 @@
 		<div class="col-sm-9">
 			<p class="lead font-weight-bold mb-0">{{Auth::user()->username}}</p>
 			<p class="">
-				<a href="#" class="font-weight-bold change-profile-photo" data-toggle="collapse" data-target="#avatarCollapse" aria-expanded="false" aria-controls="avatarCollapse">Change Profile Photo</a>
+				<a href="#" class="font-weight-bold change-profile-photo" data-toggle="collapse" data-target="#avatarCollapse" aria-expanded="false" aria-controls="avatarCollapse">{{__('settings.home.change_profile_photo')}}</a>
 			</p>
 			<div class="collapse" id="avatarCollapse">
 				<form method="post" action="/settings/avatar" enctype="multipart/form-data">
@@ -21,41 +21,41 @@
 				<div class="card card-body">
 					<div class="custom-file mb-1">
 						<input type="file" name="avatar" class="custom-file-input" id="avatarInput">
-						<label class="custom-file-label" for="avatarInput">Select a profile photo</label>
+						<label class="custom-file-label" for="avatarInput">{{__('settings.home.select_a_profile_photo')}}</label>
 					</div>
-					<p><span class="small font-weight-bold">Must be a jpeg or png. Max avatar size: <span id="maxAvatarSize"></span></span></p>
+					<p><span class="small font-weight-bold">{{__('settings.home.must_be_a_jpeg_or_png_max_avatar_size')}} <span id="maxAvatarSize"></span></span></p>
 					<div id="previewAvatar"></div>
-					<p class="mb-0"><button type="submit" class="btn btn-primary px-4 py-0 font-weight-bold">Upload</button></p>
+					<p class="mb-0"><button type="submit" class="btn btn-primary px-4 py-0 font-weight-bold">{{__('settings.home.upload')}}</button></p>
 				</div>
 				</form>
 			</div>
 			<p class="">
-				<a class="font-weight-bold text-muted delete-profile-photo" href="#">Delete Profile Photo</a>
+				<a class="font-weight-bold text-muted delete-profile-photo" href="#">{{__('settings.home.delete_profile_photo')}}</a>
 			</p>
 		</div>
 	</div>
 	<form method="post">
 		@csrf
 		<div class="form-group row">
-			<label for="name" class="col-sm-3 col-form-label font-weight-bold">Name</label>
+			<label for="name" class="col-sm-3 col-form-label font-weight-bold">{{__('settings.home.name')}}</label>
 			<div class="col-sm-9">
-				<input type="text" class="form-control" id="name" name="name" placeholder="Your Name" maxlength="30" value="{{Auth::user()->profile->name}}" v-pre>
+				<input type="text" class="form-control" id="name" name="name" placeholder="{{__('settings.home.your_name')}}" maxlength="30" value="{{Auth::user()->profile->name}}" v-pre>
 			</div>
 		</div>
 		<div class="form-group row">
-			<label for="website" class="col-sm-3 col-form-label font-weight-bold">Website</label>
+			<label for="website" class="col-sm-3 col-form-label font-weight-bold">{{__('settings.home.website')}}</label>
 			<div class="col-sm-9">
-				<input type="text" class="form-control" id="website" name="website" placeholder="Website" value="{{Auth::user()->profile->website}}" v-pre>
+				<input type="text" class="form-control" id="website" name="website" placeholder="{{__('settings.home.website')}}" value="{{Auth::user()->profile->website}}" v-pre>
 			</div>
 		</div>
 		<div class="form-group row">
-			<label for="bio" class="col-sm-3 col-form-label font-weight-bold">Bio</label>
+			<label for="bio" class="col-sm-3 col-form-label font-weight-bold">{{__('settings.home.bio')}}</label>
 			<div class="col-sm-9">
 				<textarea
 					class="form-control"
 					id="bio"
 					name="bio"
-					placeholder="Add a bio here"
+					placeholder="{{__('settings.home.add_a_bio_here')}}"
 					rows="2"
 					data-max-length="{{config('pixelfed.max_bio_length')}}"
 					maxlength="{{config('pixelfed.max_bio_length')}}"
@@ -66,7 +66,7 @@
 			</div>
 		</div>
 		<div class="form-group row">
-			<label for="language" class="col-sm-3 col-form-label font-weight-bold">Language</label>
+			<label for="language" class="col-sm-3 col-form-label font-weight-bold">{{__('settings.home.language')}}</label>
 			<div class="col-sm-9">
 				<select class="form-control" name="language">
 				@foreach(App\Util\Localization\Localization::languages() as $lang)
@@ -76,43 +76,43 @@
 			</div>
 		</div>
 		<div class="form-group row">
-			<label for="pronouns" class="col-sm-3 col-form-label font-weight-bold">Pronouns</label>
+			<label for="pronouns" class="col-sm-3 col-form-label font-weight-bold">{{__('settings.home.pronouns')}}</label>
 			<div class="col-sm-9">
 				<select class="form-control" name="pronouns[]" multiple="" id="pronouns">
-					<option>Select Pronoun(s)</option>
+					<option>{{__('settings.home.select_pronouns')}}</option>
 				@foreach(\App\Services\PronounService::pronouns() as $val)
 					<option value="{{$val}}" {{$pronouns && in_array($val, $pronouns) ? 'selected' : ''}}>{{$val}}</option>
 				@endforeach
 				</select>
-				<p class="help-text text-muted small">Select up to 4 pronouns that will appear on your profile.</p>
+				<p class="help-text text-muted small">{{__('settings.home.select_up_to_4_pronouns_that_will_appear_on_etc')}}</p>
 			</div>
 		</div>
 
         @if((bool) config_cache('federation.activitypub.enabled'))
         <div class="form-group row">
-            <label for="aliases" class="col-sm-3 col-form-label font-weight-bold">Account Aliases</label>
+            <label for="aliases" class="col-sm-3 col-form-label font-weight-bold">{{__('settings.home.account_aliases')}}</label>
             <div class="col-sm-9" id="aliases">
-                <a class="font-weight-bold" href="/settings/account/aliases/manage">Manage account alias</a>
-                <p class="help-text text-muted small">To move from another account to this one, first you need to create an alias.</p>
+                <a class="font-weight-bold" href="/settings/account/aliases/manage">{{__('settings.home.manage_account_alias')}}</a>
+                <p class="help-text text-muted small">{{__('settings.home.to_move_from_another_account_to_this_one_first_etc')}}</p>
             </div>
         </div>
 
         @if((bool) config_cache('federation.migration'))
         <div class="form-group row">
-            <label for="aliases" class="col-sm-3 col-form-label font-weight-bold">Account Migrate</label>
+            <label for="aliases" class="col-sm-3 col-form-label font-weight-bold">{{__('settings.home.account_migrate')}}</label>
             <div class="col-sm-9" id="aliases">
-                <a class="font-weight-bold" href="/settings/account/migration/manage">Migrate to another account</a>
-                <p class="help-text text-muted small">To redirect this account to a different one (where supported).</p>
+                <a class="font-weight-bold" href="/settings/account/migration/manage">{{__('settings.home.migrate_to_another_account')}}</a>
+                <p class="help-text text-muted small">{{__('settings.home.to_redirect_this_account_to_a_different_one_etc')}}</p>
             </div>
         </div>
         @endif
         @endif
 		@if(config_cache('pixelfed.enforce_account_limit'))
 		<div class="pt-3">
-			<p class="font-weight-bold text-muted text-center">Storage Usage</p>
+			<p class="font-weight-bold text-muted text-center">{{__('settings.home.storage_usage')}}</p>
 		</div>
 		<div class="form-group row">
-			<label class="col-sm-3 col-form-label font-weight-bold">Storage Used</label>
+			<label class="col-sm-3 col-form-label font-weight-bold">{{__('settings.home.storage_used')}}</label>
 			<div class="col-sm-9">
 				<div class="progress mt-2">
 					<div class="progress-bar" role="progressbar" style="width: {{$storage['percentUsed']}}%"  aria-valuenow="{{$storage['percentUsed']}}" aria-valuemin="0" aria-valuemax="100"></div>
@@ -131,7 +131,7 @@
 		<hr>
 		<div class="form-group row">
 			<div class="col-12 text-right">
-				<button type="submit" class="btn btn-primary font-weight-bold py-0 px-5">Submit</button>
+				<button type="submit" class="btn btn-primary font-weight-bold py-0 px-5">{{__('settings.submit')}}</button>
 			</div>
 		</div>
 	</form>
@@ -199,13 +199,13 @@ $(document).ready(function() {
 
 		$('.delete-profile-photo').on('click', function(e) {
 			e.preventDefault();
-			if(window.confirm('Are you sure you want to delete your profile photo.') == false) {
+			if(window.confirm('{{__('settings.home.are_you_sure_you_want_to_delete_your_profile_photo')}}') == false) {
 				return;
 			}
 			axios.delete('/settings/avatar').then(res => {
 				window.location.href = window.location.href;
 			}).catch(err => {
-				swal('Error', 'An error occured, please try again later', 'error');
+				swal('{{__('settings.error')}}', '{{__('settings.home.an_error_occured_please_try_again_later')}}', 'error');
 			});
 		});
 })

+ 1 - 1
resources/views/settings/import/ig.blade.php

@@ -3,7 +3,7 @@
 @section('section')
 
   <div class="title">
-    <h3 class="font-weight-bold">Import from Instagram</h3>
+    <h3 class="font-weight-bold">{{__('settings.import.import_from_instagram')}}</h3>
   </div>
   <hr>
   <section>

+ 4 - 4
resources/views/settings/labs.blade.php

@@ -2,8 +2,8 @@
 
 	@section('section')
 	<div class="title">
-		<h3 class="font-weight-bold">Labs</h3>
-		<p class="lead">Experimental features</p>
+		<h3 class="font-weight-bold">{{__('settings.labs')}}</h3>
+		<p class="lead">{{__('settings.labs.experimental_features')}}</p>
 	</div>
 	<hr>
 	<form method="post" id="form">
@@ -13,13 +13,13 @@
 			<label class="form-check-label font-weight-bold" for="dark_mode">
 				{{__('Dark Mode')}}
 			</label>
-			<p class="text-muted small help-text">Use dark mode theme.</p>
+			<p class="text-muted small help-text">{{__('settings.labs.use_dark_mode_theme')}}</p>
 		</div>
 
 		<div class="form-group row">
 			<div class="col-12">
 				<hr>
-				<button type="button" class="btn btn-primary font-weight-bold py-1 btn-block" id="save-btn">Save Changes</button>
+				<button type="button" class="btn btn-primary font-weight-bold py-1 btn-block" id="save-btn">{{__('settings.save')}}</button>
 			</div>
 		</div>
 	</form>

+ 9 - 9
resources/views/settings/media.blade.php

@@ -3,13 +3,13 @@
 @section('section')
 
 	<div class="title">
-		<h3 class="font-weight-bold">Media</h3>
+		<h3 class="font-weight-bold">{{__('settings.media')}}</h3>
 	</div>
 	<hr>
 	<form method="post">
 		@csrf
 		<div class="form-group pb-3">
-			<label class="form-check-label font-weight-bold" for="">Default License</label>
+			<label class="form-check-label font-weight-bold" for="">{{__('settings.media.default_license')}}</label>
 			<select class="form-control" name="default">
 				@foreach(App\Util\Media\License::get() as $license)
 				<option value="{{$license['id']}}" {{$compose['default_license'] == $license['id'] ? 'selected':''}}>
@@ -20,28 +20,28 @@
 				</option>
 				@endforeach
 			</select>
-			<p class="text-muted small help-text">Set a default license for new posts.</p>
+			<p class="text-muted small help-text">{{__('settings.media.set_a_default_license_for_new_posts')}}</p>
 		</div>
 
 		<div class="form-check pb-3">
 			<input class="form-check-input" type="checkbox" name="sync">
-			<label class="form-check-label font-weight-bold" for="">Sync Licenses</label>
-			<p class="text-muted small help-text">Update existing posts with your new default license. You can sync twice every 24 hours.<br />License changes may not be reflected on remote servers.</p>
+			<label class="form-check-label font-weight-bold" for="">{{__('settings.media.sync_licenses')}}</label>
+			<p class="text-muted small help-text">{{__('settings.media.update_existing_posts_with_your_new_default_etc')}}<br />{{__('settings.media.license_changes_may_not_be_reflected_on_remote_servers')}}</p>
 		</div>
 
 		<div class="form-check pb-3">
 			<input class="form-check-input" type="checkbox" name="media_descriptions" {{$compose['media_descriptions'] == $license['id'] ? 'checked':''}}>
-			<label class="form-check-label font-weight-bold" for="">Require Media Descriptions</label>
+			<label class="form-check-label font-weight-bold" for="">{{__('settings.media.require_media_descriptions')}}</label>
 			<p class="text-muted small help-text">
-				Briefly describe your media to improve accessibility for vision impaired people. <br />
-				<span class="font-weight-bold">Not available for mobile or 3rd party apps at this time.</span>
+				{{__('settings.media.briefly_describe_your_media_to_improve_etc')}}<br />
+				<span class="font-weight-bold">{{__('settings.media.not_available_for_mobile_or_3rd_party_apps_etc')}}</span>
 			</p>
 		</div>
 
 		<div class="form-group row mt-5 pt-5">
 			<div class="col-12 text-right">
 				<hr>
-				<button type="submit" class="btn btn-primary font-weight-bold py-0 px-5">Submit</button>
+				<button type="submit" class="btn btn-primary font-weight-bold py-0 px-5">{{__('settings.submit')}}</button>
 			</div>
 		</div>
 	</form>

+ 17 - 17
resources/views/settings/partial/sidebar.blade.php

@@ -1,39 +1,39 @@
     <div class="col-12 col-md-3">
         <ul class="nav flex-column settings-nav py-3">
             <li class="nav-item pl-3 {{request()->is('settings/home')?'active':''}}">
-                <a class="nav-link font-weight-light  text-muted" href="{{route('settings')}}">Account</a>
+                <a class="nav-link font-weight-light  text-muted" href="{{route('settings')}}">{{__('settings.account')}}</a>
             </li>
             <li class="nav-item pl-3 {{request()->is('settings/accessibility')?'active':''}}">
-                <a class="nav-link font-weight-light text-muted" href="{{route('settings.accessibility')}}">Accessibility</a>
+                <a class="nav-link font-weight-light text-muted" href="{{route('settings.accessibility')}}">{{__('settings.accessibility')}}</a>
             </li>
             <li class="nav-item pl-3 {{request()->is('settings/email')?'active':''}}">
-                <a class="nav-link font-weight-light text-muted" href="{{route('settings.email')}}">Email</a>
+                <a class="nav-link font-weight-light text-muted" href="{{route('settings.email')}}">{{__('settings.email')}}</a>
             </li>
             {{-- @if(config('pixelfed.user_invites.enabled'))
             <li class="nav-item pl-3 {{request()->is('settings/invites*')?'active':''}}">
-                <a class="nav-link font-weight-light text-muted" href="{{route('settings.invites')}}">Invites</a>
+                <a class="nav-link font-weight-light text-muted" href="{{route('settings.invites')}}">{{__('settings.invites')}}</a>
             </li>
             @endif --}}
             <li class="nav-item pl-3 {{request()->is('settings/media*')?'active':''}}">
-                <a class="nav-link font-weight-light text-muted" href="{{route('settings.media')}}">Media</a>
+                <a class="nav-link font-weight-light text-muted" href="{{route('settings.media')}}">{{__('settings.media')}}</a>
             </li>
             {{-- <li class="nav-item pl-3 {{request()->is('settings/notifications')?'active':''}}">
-                <a class="nav-link font-weight-light text-muted" href="{{route('settings.notifications')}}">Notifications</a>
+                <a class="nav-link font-weight-light text-muted" href="{{route('settings.notifications')}}">{{__('settings.notifications')}}</a>
             </li> --}}
             <li class="nav-item pl-3 {{request()->is('settings/password')?'active':''}}">
-                <a class="nav-link font-weight-light text-muted" href="{{route('settings.password')}}">Password</a>
+                <a class="nav-link font-weight-light text-muted" href="{{route('settings.password')}}">{{__('settings.password')}}</a>
             </li>
             <li class="nav-item pl-3 {{request()->is('settings/privacy*')?'active':''}}">
-                <a class="nav-link font-weight-light text-muted" href="{{route('settings.privacy')}}">Privacy</a>
+                <a class="nav-link font-weight-light text-muted" href="{{route('settings.privacy')}}">{{__('settings.privacy')}}</a>
             </li>
             <li class="nav-item pl-3 {{request()->is('settings/relationships*')?'active':''}}">
-                <a class="nav-link font-weight-light text-muted" href="{{route('settings.relationships')}}">Relationships</a>
+                <a class="nav-link font-weight-light text-muted" href="{{route('settings.relationships')}}">{{__('settings.relationships')}}</a>
             </li>
             <li class="nav-item pl-3 {{request()->is('settings/security*')?'active':''}}">
-                <a class="nav-link font-weight-light text-muted" href="{{route('settings.security')}}">Security</a>
+                <a class="nav-link font-weight-light text-muted" href="{{route('settings.security')}}">{{__('settings.security')}}</a>
             </li>
             <li class="nav-item pl-3 {{request()->is('settings/timeline*')?'active':''}}">
-                <a class="nav-link font-weight-light text-muted" href="{{route('settings.timeline')}}">Timelines</a>
+                <a class="nav-link font-weight-light text-muted" href="{{route('settings.timeline')}}">{{__('settings.timelines')}}</a>
             </li>
             <li class="nav-item">
                 <hr>
@@ -41,27 +41,27 @@
 
             @if((bool) config_cache('pixelfed.oauth_enabled') == true)
             <li class="nav-item pl-3 {{request()->is('settings/applications')?'active':''}}">
-                <a class="nav-link font-weight-light text-muted" href="{{route('settings.applications')}}">Applications</a>
+                <a class="nav-link font-weight-light text-muted" href="{{route('settings.applications')}}">{{__('settings.applications')}}</a>
             </li>
             <li class="nav-item pl-3 {{request()->is('settings/developers')?'active':''}}">
-                <a class="nav-link font-weight-light text-muted" href="{{route('settings.developers')}}">Developers</a>
+                <a class="nav-link font-weight-light text-muted" href="{{route('settings.developers')}}">{{__('settings.developers')}}</a>
             </li>
             @endif
 
             <li class="nav-item pl-3 {{request()->is('*import*')?'active':''}}">
-                <a class="nav-link font-weight-light text-muted" href="{{route('settings.import')}}">Import</a>
+                <a class="nav-link font-weight-light text-muted" href="{{route('settings.import')}}">{{__('settings.import')}}</a>
             </li>
             <li class="nav-item pl-3 {{request()->is('settings/data-export')?'active':''}}">
-                <a class="nav-link font-weight-light text-muted" href="{{route('settings.dataexport')}}">Export</a>
+                <a class="nav-link font-weight-light text-muted" href="{{route('settings.dataexport')}}">{{__('settings.export')}}</a>
             </li>
 
             <li class="nav-item pl-3 {{request()->is('settings/labs*')?'active':''}}">
-                <a class="nav-link font-weight-light text-muted" href="{{route('settings.labs')}}">Labs</a>
+                <a class="nav-link font-weight-light text-muted" href="{{route('settings.labs')}}">{{__('settings.labs')}}</a>
             </li>
 
             @if(config('instance.parental_controls.enabled'))
             <li class="nav-item pl-3 {{request()->is('settings/parental-controls*')?'active':''}}">
-                <a class="nav-link font-weight-light text-muted" href="{{route('settings.parental-controls')}}">Parental Controls</a>
+                <a class="nav-link font-weight-light text-muted" href="{{route('settings.parental-controls')}}">{{__('settings.parental_controls')}}</a>
             </li>
             @endif
         </ul>

+ 8 - 8
resources/views/settings/password.blade.php

@@ -26,33 +26,33 @@
         <div class="row">
           <div class="col-12 p-3 p-md-5">
 			  <div class="title">
-			    <h3 class="font-weight-bold">Update Password</h3>
+			    <h3 class="font-weight-bold">{{__('settings.password.update_password')}}</h3>
 			  </div>
 			  <hr>
 			  <form method="post">
 			    @csrf
 			    <div class="form-group row">
-			      <label for="existing" class="col-sm-3 col-form-label font-weight-bold">Current</label>
+			      <label for="existing" class="col-sm-3 col-form-label font-weight-bold">{{__('settings.password.current')}}</label>
 			      <div class="col-sm-9">
-			        <input type="password" class="form-control" name="current" placeholder="Your current password">
+			        <input type="password" class="form-control" name="current" placeholder="{{__('settings.password.your_current_password')}}">
 			      </div>
 			    </div>
 			    <hr>
 			    <div class="form-group row">
-			      <label for="new" class="col-sm-3 col-form-label font-weight-bold">New</label>
+			      <label for="new" class="col-sm-3 col-form-label font-weight-bold">{{__('settings.password.new')}}</label>
 			      <div class="col-sm-9">
-			        <input type="password" class="form-control" name="password" placeholder="Enter new password here">
+			        <input type="password" class="form-control" name="password" placeholder="{{__('settings.password.enter_new_password_here')}}">
 			      </div>
 			    </div>
 			    <div class="form-group row">
-			      <label for="confirm" class="col-sm-3 col-form-label font-weight-bold">Confirm</label>
+			      <label for="confirm" class="col-sm-3 col-form-label font-weight-bold">{{__('settings.password.confirm')}}</label>
 			      <div class="col-sm-9">
-			        <input type="password" class="form-control" name="password_confirmation" placeholder="Confirm new password">
+			        <input type="password" class="form-control" name="password_confirmation" placeholder="{{__('settings.password.confirm_new_password')}}">
 			      </div>
 			    </div>
 			    <div class="form-group row">
 			      <div class="col-12 text-right">
-			        <button type="submit" class="btn btn-primary font-weight-bold py-0 px-5">Submit</button>
+			        <button type="submit" class="btn btn-primary font-weight-bold py-0 px-5">{{__('settings.submit')}}</button>
 			      </div>
 			    </div>
 			  </form>

+ 31 - 31
resources/views/settings/privacy.blade.php

@@ -3,7 +3,7 @@
 @section('section')
 
   <div class="title">
-    <h3 class="font-weight-bold">Privacy Settings</h3>
+    <h3 class="font-weight-bold">{{__('settings.privacy.privacy_settings')}}</h3>
   </div>
   <hr>
   <div class="form-group pb-1">
@@ -23,7 +23,7 @@
       <label class="form-check-label font-weight-bold" for="is_private">
         {{__('Private Account')}}
       </label>
-      <p class="text-muted small help-text">When your account is private, only people you approve can see your photos and videos on pixelfed. Your existing followers won't be affected.</p>
+      <p class="text-muted small help-text">{{__('settings.privacy.when_your_account_is_private_only_people_you_etc')}}</p>
     </div>
 
     <div class="form-check pb-3">
@@ -31,7 +31,7 @@
       <label class="form-check-label font-weight-bold" for="crawlable">
         {{__('Disable Search Engine indexing')}}
       </label>
-      <p class="text-muted small help-text">When your account is visible to search engines, your information can be crawled and stored by search engines. {!! $settings->is_private ? '<strong>Not available when your account is private</strong>' : ''!!}</p>
+      <p class="text-muted small help-text">{{__('settings.privacy.when_your_account_is_visible_to_search_engines_etc')}} {!! $settings->is_private ? '<strong>'.__('settings.privacy.not_available_when_your_account_is_private').'</strong>' : ''!!}</p>
     </div>
 
     <div class="form-check pb-3">
@@ -39,7 +39,7 @@
       <label class="form-check-label font-weight-bold" for="indexable">
         {{__('Include public posts in search results')}}
       </label>
-        <p class="text-muted small help-text">Your public posts may appear in search results on Pixelfed and Mastodon. People who have interacted with your posts may be able to search them regardless. {!! $settings->is_private ? '<strong>Not available when your account is private</strong>' : ''!!}</p>
+        <p class="text-muted small help-text">{{__('settings.privacy.your_public_posts_may_appear_in_search_results_etc')}} {!! $settings->is_private ? '<strong>'.__('settings.privacy.not_available_when_your_account_is_private').'</strong>' : ''!!}</p>
     </div>
 
 
@@ -48,7 +48,7 @@
       <label class="form-check-label font-weight-bold" for="is_suggestable">
         {{__('Show on Directory')}}
       </label>
-      <p class="text-muted small help-text">When this option is enabled, your profile is included in the Directory. Only public profiles are eligible. {!! $settings->is_private ? '<strong>Not available when your account is private</strong>' : ''!!}</p>
+      <p class="text-muted small help-text">{{__('settings.privacy.when_this_option_is_enabled_your_profile_is_etc')}} {!! $settings->is_private ? '<strong>'.__('settings.privacy.not_available_when_your_account_is_private').'</strong>' : ''!!}</p>
     </div>
 
     <div class="form-check pb-3">
@@ -56,28 +56,28 @@
       <label class="form-check-label font-weight-bold" for="public_dm">
         {{__('Receive Direct Messages from anyone')}}
       </label>
-      <p class="text-muted small help-text">If selected, you will be able to receive messages and notifications from any user even if you do not follow them.</p>
+      <p class="text-muted small help-text">{{__('settings.privacy.if_selected_you_will_be_able_to_receive_messages_etc')}}</p>
     </div>
     {{-- <div class="form-check pb-3">
       <input class="form-check-input" type="checkbox" value="" id="srs" checked="">
       <label class="form-check-label font-weight-bold" for="srs">
         {{__('Hide sensitive content from search results')}}
       </label>
-      <p class="text-muted small help-text">This prevents posts with potentially sensitive content from displaying in your search results.</p>
+      <p class="text-muted small help-text">{{__('settings.privacy.this_prevents_posts_with_potentially_sensitive_etc')}}</p>
     </div> --}}
     {{-- <div class="form-check pb-3">
       <input class="form-check-input" type="checkbox" value="" id="rbma" checked="">
       <label class="form-check-label font-weight-bold" for="rbma">
         {{__('Remove blocked and muted accounts')}}
       </label>
-      <p class="text-muted small help-text">Use this to eliminate search results from accounts you've blocked or muted.</p>
+      <p class="text-muted small help-text">{{__('settings.privacy.use_this_to_eliminate_search_results_from_accounts_etc')}}</p>
     </div>
     <div class="form-check pb-3">
       <input class="form-check-input" type="checkbox" value="" id="ssp">
       <label class="form-check-label font-weight-bold" for="ssp">
         {{__('Display media that may contain sensitive content')}}
       </label>
-      <p class="text-muted small help-text">Show all media, including potentially sensitive content.</p>
+      <p class="text-muted small help-text">{{__('settings.privacy.show_all_media_including_potentially_sensitive_content')}}</p>
     </div> --}}
 
     <div class="form-check pb-3">
@@ -85,7 +85,7 @@
       <label class="form-check-label font-weight-bold" for="show_profile_follower_count">
         {{__('Show Follower Count')}}
       </label>
-      <p class="text-muted small help-text">Display follower count on profile</p>
+      <p class="text-muted small help-text">{{__('settings.privacy.display_follower_count_on_profile')}}</p>
     </div>
 
 
@@ -94,7 +94,7 @@
       <label class="form-check-label font-weight-bold" for="show_profile_following_count">
         {{__('Show Following Count')}}
       </label>
-      <p class="text-muted small help-text">Display following count on profile</p>
+      <p class="text-muted small help-text">{{__('settings.privacy.display_following_count_on_profile')}}</p>
     </div>
 
     <div class="form-check pb-3">
@@ -102,7 +102,7 @@
       <label class="form-check-label font-weight-bold" for="disable_embeds">
         {{__('Disable Embeds')}}
       </label>
-      <p class="text-muted small help-text">Disable post and profile embeds</p>
+      <p class="text-muted small help-text">{{__('settings.privacy.disable_post_and_profile_embeds')}}</p>
     </div>
 
     @if(!$settings->is_private)
@@ -111,7 +111,7 @@
       <label class="form-check-label font-weight-bold" for="show_atom">
         {{__('Enable Atom Feed')}}
       </label>
-      <p class="text-muted small help-text mb-0">Enable your profile atom feed. Only public profiles are eligible.</p>
+      <p class="text-muted small help-text mb-0">{{__('settings.privacy.enable_your_profile_atom_feed_only_public_profiles_etc')}}</p>
       @if($settings->show_atom)
       <p class="small">
          <a href="{{$profile->permalink('.atom')}}" class="text-success font-weight-bold small" target="_blank">
@@ -126,7 +126,7 @@
     <div class="form-group row mt-5 pt-5">
       <div class="col-12 text-right">
         <hr>
-        <button type="submit" class="btn btn-primary font-weight-bold py-0 px-5">Submit</button>
+        <button type="submit" class="btn btn-primary font-weight-bold py-0 px-5">{{__('settings.submit')}}</button>
       </div>
     </div>
   </form>
@@ -134,63 +134,63 @@
   <div class="modal-dialog" role="document">
     <div class="modal-content">
       <div class="modal-header">
-        <h5 class="modal-title">Confirm this action</h5>
+        <h5 class="modal-title">{{__('settings.privacy.confirm_this_action')}}</h5>
         <button type="button" class="close" data-dismiss="modal" aria-label="Close">
           <span aria-hidden="true">&times;</span>
         </button>
       </div>
       <div class="modal-body p-3">
-        <p class="font-weight-bold">Please select the type of private account you would like:</p>
+        <p class="font-weight-bold">{{__('settings.privacy.please_select_the_type_of_private_account_you_etc')}}</p>
         <div>
           <div class="form-check">
             <input class="form-check-input" type="radio" id="fm-1" name="pfType" value="keep-all" checked>
             <label class="form-check-label pb-2 font-weight-bold" for="fm-1">
-              Keep existing followers
+              {{__('settings.privacy.keep_existing_followers')}}
             </label>
           </div>
           <div class="form-check">
             <input class="form-check-input" type="radio" id="fm-2" name="pfType" value="mutual-only">
             <label class="form-check-label pb-2 font-weight-bold" for="fm-2">
-              Only keep mutual followers
+              {{__('settings.privacy.only_keep_mutual_followers')}}
             </label>
           </div>
           <div class="form-check">
             <input class="form-check-input" type="radio" id="fm-3" name="pfType" value="only-followers">
             <label class="form-check-label pb-2 font-weight-bold" for="fm-3">
-              Only followers that have followed you for atleast <select name="pfDuration">
-                  <option value="60">1 hour</option>
-                  <option value="1440">1 day</option>
-                  <option value="20160">2 weeks</option>
-                  <option value="43200">1 month</option>
-                  <option value="259200">6 months</option>
-                  <option value="525600">1 year</option>
+              {{__('settings.privacy.only_followers_that_have_followed_you_for_atleast')}} <select name="pfDuration">
+                  <option value="60">1 {{__('settings.privacy.hour')}}</option>
+                  <option value="1440">1 {{__('settings.privacy.day')}}</option>
+                  <option value="20160">2 {{__('settings.privacy.weeks')}}</option>
+                  <option value="43200">1 {{__('settings.privacy.month')}}</option>
+                  <option value="259200">6 {{__('settings.privacy.months')}}</option>
+                  <option value="525600">1 {{__('settings.privacy.year')}}</option>
                 </select>
             </label>
           </div>
           <div class="form-check">
             <input class="form-check-input" type="radio" id="fm-4" name="pfType" value="remove-all">
             <label class="form-check-label font-weight-bold text-danger" for="fm-4">
-              Remove existing followers
+              {{__('settings.privacy.remove_existing_followers')}}
             </label>
           </div>
           {{-- <hr>
           <div class="form-check pt-3">
             <input class="form-check-input" type="checkbox" id="allowFollowRequest">
             <label class="form-check-label" for="allowFollowRequest">
-              Allow new follow requests
+              {{__('settings.privacy.allow_new_follow_requests')}}
             </label>
           </div>
           <div class="form-check">
             <input class="form-check-input" type="checkbox" name="blockNotifications" id="chk4">
             <label class="form-check-label" for="chk4">
-              Block notifications from accounts I don't follow
+              {{__('settings.privacy.block_notifications_from_accounts_i_dont_follow')}}
             </label>
           </div> --}}
         </div>
       </div>
       <div class="modal-footer">
-        <button type="button" class="btn btn-outline-secondary font-weight-bold py-0" data-dismiss="modal">Cancel</button>
-        <button type="button" class="btn btn-primary font-weight-bold py-0" id="modal_confirm">Save</button>
+        <button type="button" class="btn btn-outline-secondary font-weight-bold py-0" data-dismiss="modal">{{__('settings.cancel')}}</button>
+        <button type="button" class="btn btn-primary font-weight-bold py-0" id="modal_confirm">{{__('settings.save')}}</button>
       </div>
     </div>
   </div>
@@ -220,7 +220,7 @@
       }).then(res => {
         window.location.href = window.location.href;
       }).catch(err => {
-        swal('Error', 'An error occured. Please try again.', 'error');
+        swal('{{__('settings.error')}}', '{{__('settings.privacy.an_error_occured_please_try_again')}}', 'error');
       });
     });
   });

+ 20 - 20
resources/views/settings/relationships/home.blade.php

@@ -3,14 +3,14 @@
 @section('section')
 
 <div class="title">
-	<h3 class="font-weight-bold">Relationships</h3>
+	<h3 class="font-weight-bold">{{__('settings.relationships')}}</h3>
 </div>
 <hr>
 <div class="form-group pb-1">
     <p>
-        <a class="btn py-0 btn-link {{!request()->has('mode') || $mode == 'followers' ? 'font-weight-bold' : 'text-muted'}}" href="?mode=followers&page=1">Followers</a>
-        <a class="btn btn-link py-0  {{$mode == 'following' ? 'font-weight-bold' : 'text-muted'}}" href="?mode=following&page=1">Following</a>
-        <a class="btn btn-link py-0 {{$mode == 'hashtags' ? 'font-weight-bold' : 'text-muted'}}" href="?mode=hashtags&page=1">Hashtags</a>
+        <a class="btn py-0 btn-link {{!request()->has('mode') || $mode == 'followers' ? 'font-weight-bold' : 'text-muted'}}" href="?mode=followers&page=1">{{__('settings.relationships.followers')}}</a>
+        <a class="btn btn-link py-0  {{$mode == 'following' ? 'font-weight-bold' : 'text-muted'}}" href="?mode=following&page=1">{{__('settings.relationships.following')}}</a>
+        <a class="btn btn-link py-0 {{$mode == 'hashtags' ? 'font-weight-bold' : 'text-muted'}}" href="?mode=hashtags&page=1">{{__('settings.relationships.hashtags')}}</a>
     </p>
 </div>
 
@@ -25,8 +25,8 @@
 			{{-- <th scope="col" class="pt-0 pb-1 mt-0">
 				<input type="checkbox" name="check" class="form-control check-all">
 			</th> --}}
-			<th scope="col">Hashtag</th>
-			<th scope="col">Action</th>
+			<th scope="col">{{__('settings.relationships.hashtag')}}</th>
+			<th scope="col">{{__('settings.relationships.action')}}</th>
 		</tr>
 	</thead>
 	<tbody>
@@ -48,8 +48,8 @@
 			{{-- <th scope="col" class="pt-0 pb-1 mt-0">
 				<input type="checkbox" name="check" class="form-control check-all">
 			</th> --}}
-			<th scope="col">Username</th>
-			<th scope="col">Action</th>
+			<th scope="col">{{__('settings.relationships.username')}}</th>
+			<th scope="col">{{__('settings.relationship.action')}}</th>
 		</tr>
 	</thead>
 	<tbody>
@@ -69,8 +69,8 @@
 			</td>
 			@else
 			<td class="text-center">
-				<a class="btn btn-outline-primary btn-sm py-0 action-btn" href="#" data-id="{{$follower->id}}" data-action="mute">Mute</a>
-				<a class="btn btn-outline-danger btn-sm py-0 action-btn" href="#" data-id="{{$follower->id}}" data-action="block">Block</a>
+				<a class="btn btn-outline-primary btn-sm py-0 action-btn" href="#" data-id="{{$follower->id}}" data-action="mute">{{__('settings.relationships.mute')}}</a>
+				<a class="btn btn-outline-danger btn-sm py-0 action-btn" href="#" data-id="{{$follower->id}}" data-action="block">{{__('settings.relationships.block')}}</a>
 			</td>
 			@endif
 		</tr>
@@ -106,8 +106,8 @@
 					item: id
 				}).then(res => {
 					swal(
-						'Mute Successful',
-						'You have successfully muted that user',
+						'{{__('settings.relationships.mute_successful')}}',
+						'{{__('settings.relationships.you_have_successfully_muted_that_user')}}',
 						'success'
 						);
 				});
@@ -119,8 +119,8 @@
 					item: id
 				}).then(res => {
 					swal(
-						'Block Successful',
-						'You have successfully blocked that user',
+						'{{__('settings.relationships.block_successful')}}',
+						'{{__('settings.relationships.you_have_successfully_blocked_that_user')}}',
 						'success'
 						);
 				});
@@ -130,15 +130,15 @@
 				axios.post('/api/v1/accounts/' + id + '/unfollow')
 				.then(res => {
 					swal(
-						'Unfollow Successful',
-						'You have successfully unfollowed that user',
+						'{{__('settings.relationships.unfollow_successful')}}',
+						'{{__('settings.relationships.you_have_successfully_unfollowed_that_user')}}',
 						'success'
 						);
 				})
 				.catch(err => {
 					swal(
-						'Error',
-						'An error occured when attempting to unfollow this user',
+						'{{__('settings.error')}}',
+						'{{__('settings.relationships.an_error_occured_when_attempting_to_unfollow_this_user')}}',
 						'error'
 						);
 				});
@@ -147,8 +147,8 @@
 				case 'unfollowhashtag':
 				axios.post('/api/v1/tags/' + id + '/unfollow').then(res => {
 					swal(
-						'Unfollow Successful',
-						'You have successfully unfollowed that hashtag',
+						'{{__('settings.relationships.unfollow_successful')}}',
+						'{{__('settings.relationships.you_have_successfully_unfollowed_that_hashtag')}}',
 						'success'
 						);
 				});

+ 10 - 10
resources/views/settings/security.blade.php

@@ -3,16 +3,16 @@
 @section('section')
 
   <div class="title">
-    <h3 class="font-weight-bold">Security</h3>
+    <h3 class="font-weight-bold">{{__('settings.security')}}</h3>
   </div>
   <hr>
 
   <section class="pt-4">
     <div class="mb-4 pb-4">
       <div class="d-flex justify-content-between align-items-center">
-        <h4 class="font-weight-bold mb-0">Two-factor authentication</h4>
+        <h4 class="font-weight-bold mb-0">{{__('settings.security.two_factor_authentication')}}</h4>
         @if($user->{'2fa_enabled'})
-        <a class="btn btn-success btn-sm font-weight-bold" href="#">Enabled</a>
+        <a class="btn btn-success btn-sm font-weight-bold" href="#">{{__('settings.security.enabled')}}</a>
         @endif
       </div>
       <hr>
@@ -28,25 +28,25 @@
     @include('settings.security.device-panel')
 
     @if(config('pixelfed.account_deletion') && !$user->is_admin)
-    <h4 class="font-weight-bold pt-3">Danger Zone</h4>
+    <h4 class="font-weight-bold pt-3">{{__('settings.security.danger_zone')}}</h4>
     <div class="mb-4 border rounded border-danger">
       <ul class="list-group mb-0 pb-0">
         <li class="list-group-item border-left-0 border-right-0 py-3 d-flex justify-content-between">
           <div>
-            <p class="font-weight-bold mb-1">Temporarily Disable Account</p>
-            <p class="mb-0 small">Disable your account to hide your posts until next log in.</p>
+            <p class="font-weight-bold mb-1">{{__('settings.security.temporarily_disable_account')}}</p>
+            <p class="mb-0 small">{{__('settings.security.disable_your_account_to_hide_your_posts_until_next_log_in')}}</p>
           </div>
           <div>
-            <a class="btn btn-outline-danger font-weight-bold py-1" href="{{route('settings.remove.temporary')}}">Disable</a>
+            <a class="btn btn-outline-danger font-weight-bold py-1" href="{{route('settings.remove.temporary')}}">{{__('settings.security.disable')}}</a>
           </div>
         </li>
         <li class="list-group-item border-left-0 border-right-0 py-3 d-flex justify-content-between">
           <div>
-            <p class="font-weight-bold mb-1">Delete this Account</p>
-            <p class="mb-0 small">Once you delete your account, there is no going back. Please be certain.</p>
+            <p class="font-weight-bold mb-1">{{__('settings.security.delete_this_account')}}</p>
+            <p class="mb-0 small">{{__('settings.security.once_you_delete_your_account_there_is_no_going_back_etc')}}</p>
           </div>
           <div>
-            <a class="btn btn-outline-danger font-weight-bold py-1" href="{{route('settings.remove.permanent')}}">Delete</a>
+            <a class="btn btn-outline-danger font-weight-bold py-1" href="{{route('settings.remove.permanent')}}">{{__('settings.security.delete')}}</a>
           </div>
         </li>
       </ul>

+ 8 - 8
resources/views/settings/security/device-panel.blade.php

@@ -1,5 +1,5 @@
 <div class="mb-4 pb-4">
-  <h4 class="font-weight-bold">Devices</h4>
+  <h4 class="font-weight-bold">{{__('settings.security.devices')}}</h4>
   <hr>
   <ul class="list-group">
     @foreach($devices as $device)
@@ -14,30 +14,30 @@
         </div>
         <div>
           <p class="mb-0 font-weight-bold">
-            <span class="text-muted">IP:</span>
+            <span class="text-muted">{{__('settings.security.ip')}}</span>
             <span class="text-truncate">{{$device->ip}}</span>
           </p>
           <p class="mb-0 font-weight-bold">
-            <span class="text-muted">Device:</span>
+            <span class="text-muted">{{__('settings.security.device')}}</span>
             <span>{{$device->getUserAgent()->device()}}</span>
           </p>
           <p class="mb-0 font-weight-bold">
-            <span class="text-muted">Browser:</span>
+            <span class="text-muted">{{__('settings.security.browser')}}</span>
             <span>{{$device->getUserAgent()->browser()}}</span>
           </p>
           {{-- <p class="mb-0 font-weight-bold">
-            <span class="text-muted">Country:</span>
+            <span class="text-muted">{{__('settings.security.country')}}</span>
             <span>Canada</span>
           </p> --}}
           <p class="mb-0 font-weight-bold">
-            <span class="text-muted">Last Login:</span>
+            <span class="text-muted">{{__('settings.security.last_login')}}</span>
             <span>{{$device->updated_at->diffForHumans()}}</span>
           </p>
         </div>
         <div>
           <div class="btn-group">
-            {{-- <a class="btn btn-success font-weight-bold py-0 btn-sm" href="#">Trust</a>
-            <a class="btn btn-outline-secondary font-weight-bold py-0 btn-sm" href="#">Remove Device</a> --}}
+            {{-- <a class="btn btn-success font-weight-bold py-0 btn-sm" href="#">{{__('settings.security.trust')}}</a>
+            <a class="btn btn-outline-secondary font-weight-bold py-0 btn-sm" href="#">{{__('settings.security.remove_device')}}</a> --}}
           </div>
         </div>
       </div>

+ 4 - 4
resources/views/settings/security/log-panel.blade.php

@@ -1,9 +1,9 @@
     <div class="mb-4 pb-4">
-      <h4 class="font-weight-bold">Account Log</h4>
+      <h4 class="font-weight-bold">{{__('settings.security.account_log')}}</h4>
       <hr>
       <ul class="list-group border" style="max-height: 400px;overflow-y: auto;">
         @if($activity->count() == 0) 
-        <p class="alert alert-info font-weight-bold">No activity logs found!</p>
+        <p class="alert alert-info font-weight-bold">{{__('settings.security.no_activity_logs_found')}}</p>
         @endif
         @foreach($activity as $log)
         <li class="list-group-item rounded-0 border-0">
@@ -21,13 +21,13 @@
               <div class="collapse" id="log-details-{{$log->id}}">
               	<div class="py-2">
               		<p class="mb-0">
-              			<span class="font-weight-bold">IP Address:</span>
+              			<span class="font-weight-bold">{{__('settings.security.ip_address')}}</span>
               			<span>
               				{{$log->ip_address}}
               			</span>
               		</p>
             		<p class="mb-0">
-              			<span class="font-weight-bold">User Agent:</span>
+              			<span class="font-weight-bold">{{__('settings.security.user_agent')}}</span>
               			<span>
               				{{$log->user_agent}}
               			</span>

+ 10 - 10
resources/views/settings/timeline.blade.php

@@ -3,38 +3,38 @@
 @section('section')
 
 	<div class="title">
-		<h3 class="font-weight-bold">Timeline Settings</h3>
+		<h3 class="font-weight-bold">{{__('settings.security.timeline_settings')}}</h3>
 	</div>
 	<hr>
 	<form method="post">
 		@csrf
 		<div class="form-check pb-3 d-none">
 			<input class="form-check-input" type="checkbox" name="top" {{$top ? 'checked':''}}>
-			<label class="form-check-label font-weight-bold" for="">Show text-only posts</label>
-			<p class="text-muted small help-text">Show text-only posts from accounts you follow. (Home timeline only)</p>
+			<label class="form-check-label font-weight-bold" for="">{{__('settings.security.show_text_only_posts')}}</label>
+			<p class="text-muted small help-text">{{__('settings.security.show_text_only_posts_from_accounts_you_follow_home_etc')}}</p>
 		</div>
 		<div class="form-check pb-3 d-none">
 			<input class="form-check-input" type="checkbox" name="replies" {{$replies ? 'checked':''}}>
-			<label class="form-check-label font-weight-bold" for="">Show replies</label>
-			<p class="text-muted small help-text">Show replies from accounts you follow. (Home timeline only)</p>
+			<label class="form-check-label font-weight-bold" for="">{{__('settings.security.show_replies')}}</label>
+			<p class="text-muted small help-text">{{__('settings.security.show_replies_from_accounts_you_follow_home_timeline_only')}}</p>
 		</div>
 
         <div class="form-check pb-3">
             <input class="form-check-input" type="checkbox" name="enable_reblogs" {{$userSettings['enable_reblogs'] ? 'checked':''}}>
-            <label class="form-check-label font-weight-bold" for="">Show reblogs</label>
-            <p class="text-muted small help-text">See reblogs from accounts you follow in your home feed. (Home timeline only)</p>
+            <label class="form-check-label font-weight-bold" for="">{{__('settings.security.show_reblogs')}}</label>
+            <p class="text-muted small help-text">{{__('settings.security.see_reblogs_from_accounts_you_follow_in_your_home_etc')}}</p>
         </div>
 
         <div class="form-check pb-3">
             <input class="form-check-input" type="checkbox" name="photo_reblogs_only" {{$userSettings['photo_reblogs_only'] ? 'checked':''}}>
-            <label class="form-check-label font-weight-bold" for="">Photo reblogs only</label>
-            <p class="text-muted small help-text">Only see reblogs of photos or photo albums. (Home timeline only)</p>
+            <label class="form-check-label font-weight-bold" for="">{{__('settings.security.photo_reblogs_only')}}</label>
+            <p class="text-muted small help-text">{{__('settings.security.only_see_reblogs_of_photos_or_photo_albums_home_etc')}}</p>
         </div>
 
 		<div class="form-group row mt-5 pt-5">
 			<div class="col-12 text-right">
 				<hr>
-				<button type="submit" class="btn btn-primary font-weight-bold py-0 px-5">Submit</button>
+				<button type="submit" class="btn btn-primary font-weight-bold py-0 px-5">{{__('settings.submit')}}</button>
 			</div>
 		</div>
 	</form>

+ 21 - 20
resources/views/site/about.blade.php

@@ -36,10 +36,11 @@
 			<a href="/">
 				<img class="d-block mx-auto mb-4" src="/img/pixelfed-icon-color.svg" alt="" width="72" height="57">
 			</a>
-			<h1 class="display-4 font-weight-bold py-3">{{ config_cache('about.title') ?? 'Photo Sharing. For Everyone' }}</h1>
+			
+			<h1 class="display-4 font-weight-bold py-3">{{ config_cache('about.title') ?? __('site.photo_sharing_for_everyone') }}</h1>
 			<div class="col-lg-6 mx-auto py-3">
 			  <p class="mb-4 font-weight-light text-left" style="font-size: 26px; line-height: 40px;">
-				{!! config_cache('app.description') ?? config_cache('app.short_description') ?? 'Pixelfed is an image sharing platform, an ethical alternative to centralized platforms.'!!}
+				{!! config_cache('app.description') ?? config_cache('app.short_description') ?? __('site.pixelfed_is_an_image_sharing_platform_etc') !!}
 			  </p>
 			</div>
 		</div>
@@ -126,10 +127,10 @@
 			<div class="row">
 				<div class="col-12 col-md-8 offset-md-2">
 					<div class="mt-5">
-						<p class="text-center display-4 font-weight-bold">Feature Packed.</p>
+						<p class="text-center display-4 font-weight-bold">{{__('site.feature_packed')}}</p>
 					</div>
 					<div class="my-2">
-						<p class="h3 font-weight-light text-muted text-center">The best for the brightest 📸</p>
+						<p class="h3 font-weight-light text-muted text-center">{{__('site.the_best_for_the_brightest')}}</p>
 					</div>
 				</div>
 			</div>
@@ -137,8 +138,8 @@
 		<div class="container my-5">
 			<div class="row p-4 pb-0 pt-lg-5 align-items-center rounded-3">
 				<div class="col-lg-6 p-3 p-lg-5 pt-lg-3">
-					<h1 class="display-4 font-weight-bold lh-1">Albums</h1>
-					<p class="h4 font-weight-light">Share posts with up to {{config_cache('pixelfed.max_album_length')}} photos</p>
+					<h1 class="display-4 font-weight-bold lh-1">{{__('site.albums')}}</h1>
+					<p class="h4 font-weight-light">{{__('site.share_posts_with_up_to')}} {{config_cache('pixelfed.max_album_length')}} {{__('site.photos')}}</p>
 				</div>
 				<div class="col-lg-6 overflow-hidden">
 					<img class="rounded-lg img-fluid filter-inkwell" src="/_landing/1.jpeg" alt="" width="720">
@@ -152,8 +153,8 @@
 					<img class="rounded-lg img-fluid filter-inkwell" src="/_landing/2.jpeg" alt="" width="720">
 				</div>
 				<div class="col-lg-6 p-3 p-lg-5 pt-lg-3">
-					<h1 class="display-4 font-weight-bold lh-1">Comments</h1>
-					<p class="h4 font-weight-light text-justify">Comment on a post, or send a reply</p>
+					<h1 class="display-4 font-weight-bold lh-1">{{__('site.comments')}}</h1>
+					<p class="h4 font-weight-light text-justify">{{__('site.comment_on_a_post_or_send_a_reply')}}</p>
 				</div>
 			</div>
 		</div>
@@ -161,8 +162,8 @@
 		<div class="container my-5">
 			<div class="row p-4 pb-0 pt-lg-5 align-items-center rounded-3">
 				<div class="col-lg-6 p-3 p-lg-5 pt-lg-3">
-					<h1 class="display-4 font-weight-bold lh-1">Collections</h1>
-					<p class="h4 font-weight-light text-justify">Organize and share collections of multiple posts</p>
+					<h1 class="display-4 font-weight-bold lh-1">{{__('site.collections')}}</h1>
+					<p class="h4 font-weight-light text-justify">{{__('site.organize_and_share_collections_of_multiple_posts')}}</p>
 				</div>
 				<div class="col-lg-6 overflow-hidden">
 					<img class="rounded-lg img-fluid filter-inkwell" src="/_landing/3.jpeg" alt="" width="720">
@@ -176,8 +177,8 @@
 					<img class="rounded-lg img-fluid filter-inkwell" src="/_landing/4.jpeg" alt="" width="720">
 				</div>
 				<div class="col-lg-6 p-3 p-lg-5 pt-lg-3">
-					<h1 class="display-4 font-weight-bold lh-1">Discover</h1>
-					<p class="h4 font-weight-light text-justify">Explore categories, hashtags and topics</p>
+					<h1 class="display-4 font-weight-bold lh-1">{{__('site.discover')}}</h1>
+					<p class="h4 font-weight-light text-justify">{{__('site.explore_categories_hashtags_and_topics')}}</p>
 				</div>
 			</div>
 		</div>
@@ -185,8 +186,8 @@
 		<div class="container my-5">
 			<div class="row p-4 pb-0 pt-lg-5 align-items-center rounded-3">
 				<div class="col-lg-6 p-3 p-lg-5 pt-lg-3">
-					<h1 class="display-4 font-weight-bold lh-1">Photo Filters</h1>
-					<p class="h4 font-weight-light text-justify">Add a special touch to your photos</p>
+					<h1 class="display-4 font-weight-bold lh-1">{{__('site.photo_filters')}}</h1>
+					<p class="h4 font-weight-light text-justify">{{__('site.add_a_special_touch_to_your_photos')}}</p>
 				</div>
 				<div class="col-lg-6 overflow-hidden">
 					<img class="rounded-lg img-fluid filter-inkwell" src="/_landing/5.jpeg" alt="" width="720">
@@ -200,8 +201,8 @@
 					<img class="rounded-lg img-fluid filter-inkwell" src="/_landing/6.jpeg" alt="" width="720">
 				</div>
 				<div class="col-lg-6 p-3 p-lg-5 pt-lg-3">
-					<h1 class="display-4 font-weight-bold lh-1">Stories</h1>
-					<p class="h4 font-weight-light text-justify">Share moments with your followers that disappear after 24 hours</p>
+					<h1 class="display-4 font-weight-bold lh-1">{{__('site.stories')}}</h1>
+					<p class="h4 font-weight-light text-justify">{{__('site.share_moments_with_your_followers_that_disappear_etc')}}</p>
 				</div>
 			</div>
 		</div>
@@ -214,15 +215,15 @@
 				<div class="col">
 					<p class="display-3 font-weight-bold">
 						<span class="text-primary">{{$user_count}}</span>
-						people have shared
+						{{__('site.people_have_shared')}}
 						<span class="text-primary">{{$post_count}}</span>
-						photos and videos on {{config_cache('app.name')}}!
+						{{__('site.photos_and_videos_on')}} {{config_cache('app.name')}}!
 					</p>
 					@if(config_cache('pixelfed.open_registration'))
 					<div class="section-spacer"></div>
 					<p class="display-4 font-weight-bold mb-0">
-						<a class="text-primary" href="/register">Sign up today</a>
-						and join our community of photographers from around the world.
+						<a class="text-primary" href="/register">{{__('site.sign_up_today')}}</a>
+						{{__('site.and_join_our_community_of_photographers_from_etc')}}
 					</p>
 					@endif
 				</div>

+ 5 - 5
resources/views/site/fediverse.blade.php

@@ -7,15 +7,15 @@
   </div>
   <hr>
   <section>
-    <p class="lead"><a href="http://fediverse.party/" rel="nofollow noopener">Fediverse</a> is a portmanteau of “federation” and “universe”. It is a common, informal name for a federation of social network servers, specializing in different types of media.</p>
-    <p class="lead font-weight-bold text-muted mt-4 mb-0">Supported Fediverse Projects</p>
-    <p class="small text-muted">Some of the better known fediverse projects include:</p>
+    <p class="lead"><a href="http://fediverse.party/" rel="nofollow noopener">Fediverse</a> {{__('site.is_a_portmanteau_of_federation_and_universe_etc')}}</p>
+    <p class="lead font-weight-bold text-muted mt-4 mb-0">{{__('site.supported_fediverse_projects')}}</p>
+    <p class="small text-muted">{{__('site.some_of_the_better_known_fediverse_projects_include')}}</p>
     <ul class="lead pl-4">
-      <li><a href="https://joinmastodon.org" rel="nofollow noopener">Mastodon</a> – A federated microblogging alternative.</li>
+      <li><a href="https://joinmastodon.org" rel="nofollow noopener">Mastodon</a> – {{__('site.a_federated_microblogging_alternative')}}</li>
     </ul>
   </section>
 @endsection
 
 @push('meta')
-<meta property="og:description" content="Fediverse is a portmanteau of “federation” and “universe”. It is a common, informal name for a federation of social network servers, specializing in different types of media.">
+<meta property="og:description" content="Fediverse {{__('site.is_a_portmanteau_of_federation_and_universe_etc')}}">
 @endpush

+ 2 - 2
resources/views/site/opensource.blade.php

@@ -7,10 +7,10 @@
   </div>
   <hr>
   <section>
-    <p class="lead">The software that powers this website is called <a href="https://pixelfed.org">Pixelfed</a> and anyone can <a href="https://github.com/pixelfed/pixelfed">download</a> or <a href="https://github.com/pixelfed/pixelfed">view</a> the source code and run their own instance!</p>
+    <p class="lead">{{__('site.the_software_that_powers_this_website_is_called')}} <a href="https://pixelfed.org">Pixelfed</a> {{__('site.and_anyone_can')}} <a href="https://github.com/pixelfed/pixelfed">{{__('site.download')}}</a> {{__('site.opensource.or')}} <a href="https://github.com/pixelfed/pixelfed">{{__('site.view')}}</a> {{__('site.the_source_code_and_run_their_own_instance')}}</p>
   </section>
 @endsection
 
 @push('meta')
-<meta property="og:description" content="Open source in Pixelfed">
+<meta property="og:description" content="{{__('site.open_source_in_pixelfed')}}">
 @endpush